UVA - 10766 Organising the Organisation (生成树计数-补图) 基尔霍夫矩阵

该博客详细介绍了UVA 10766问题——Organising the Organisation,讨论如何在给定n个点、m对不能相连的点及根节点k的情况下,计算补图的生成树数量。通过基尔霍夫矩阵树定理,解释了无向图生成树数目与n-1阶主子式的行列式的绝对值的关系,并指出生成树数与根节点k无关。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                UVA - 10766  Organising the Organisation

题意: 

          给你 n个点,m条边,以及一个k, m条边代表这m对点不能相连,k代表根节点。求有多少生成树。

 

题解:

        1.注意是补图

        2.生成树计数

请点击: 基尔霍夫矩阵树定理

无向图的基尔霍夫矩阵: 对角线上表示每个点的度数,若ij之间有边则矩阵ij处为-1

无向图的生成树的数目为: 任意一个n-1阶主子式的行列式的绝对值.

Cayley公式:完全图Kn有n^(n-2)颗生成树。

          3.仔细思考一下,生成树的数目和根节点没有关系,所以与k无关

 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 60 + 10;
const int maxm = 1010025;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
#define type long long
int n,m;

int d[maxn];
int g[maxn][maxn];
type c[maxn][maxn];

type det(type a[][maxn],int n)
{
  type ret=1;
  for(int i=1;i<=n;i++)
  {
    for(int j=i+1;j<=n;j++)
    {
      while(a[j][i])
      {
        type t=a[i][i]/a[j][i];
        for(int k=i;k<=n;k++)
            a[i][k]=a[i][k]-a[j][k]*t;

        for(int k=i;k<=n;k++)
            swap(a[i][k],a[j][k]);
        ret=-ret;
      }
    }
    if(a[i][i]==0)  return 0;
    ret=ret*a[i][i];
  }
  if(ret<0)   ret=-ret;
  return ret;
}

type num_st(int n, int m)
{
     for(int i = 1; i <= n; i++)
       for(int j = 1; j <= n; j++)
         {
           if(i == j) c[i][j] = d[i];
           else c[i][j] = -g[i][j];
         }
/*
    for(int i = 1; i <= n; i++)
     for(int j = 1; j <= n; j++)
        printf("%lld%c",c[i][j],j == n ? '\n' : ' ');
*/
    return det(c,n-1);
}
int main()
{
  while(~scanf("%d%d%d",&n,&m,&k))
  {
    memset(d,0,sizeof(d));
    for(int i = 1; i <= n; i++)
      for(int j = 1; j <= n; j++)
           g[i][j] = 1;
    for(int i = 0; i < m; i++)
    {
      int u,v;
      scanf("%d%d",&u,&v);
      g[u][v]=g[v][u]= 0;
    }
    for(int i = 1; i <= n; i++)
      for(int j = 1; j <= n; j++)
         if(i != j)d[i] += g[i][j];

    type ans = num_st(n,m);
    printf("%lld\n",ans);
  }
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值