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;
}