题目大意:给定一张无向图G,问用G中的边可建成多少棵树。
生成树定理,也叫矩阵树定理模板。
神奇的算法~用矩阵快速求出生成树个数~
对于每个点,a[i][i]为i点的度数,如果i与j之间有边相连,则a[i][j]减1,然后行列式求n-1矩阵的值即可。
行列式的求法:
将矩阵高斯消元到倒三角的模式(就是解方程组最后一步时的样子),然后将对角线上的数相乘取绝对值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#define ll long long
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')c=getchar(),f=-1;
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=15;
int T,n,m;
double a[N][N];
double calc()
{
double b,ans=1;
for(int i=1;i<=n;i++)
{
if(a[i][i]==0)
{
int bz=0;
for(int j=i+1;j<=n;j++)
if(a[j][i])
{
bz=1;
for(int k=i;k<=n;k++)
swap(a[i][k],a[j][k]);
break;
}
if(!bz)return 0;
}
ans*=a[i][i];
for(int j=i+1;j<=n;j++)
{
b=a[j][i]*1.0/a[i][i];
for(int k=i;k<=n;k++)
a[j][k]-=b*a[i][k];
}
}
if(ans<0)ans=-ans;
return ans;
}
int main()
{
//freopen("lx.in","r",stdin);
int x,y;
T=getint();
while(T--)
{
memset(a,0,sizeof(a));
n=getint(),m=getint();
if(n==1)
{
puts("1");
continue;
}
while(m--)
{
x=getint(),y=getint();
a[x][x]++,a[y][y]++;
a[x][y]--,a[y][x]--;
}
n--;
printf("%0.0lf\n",calc());
}
return 0;
}