Problem 2. tcount
Input file: tcount.in
Output file: tcount.out
Time limit: 1 second
Mr.H发现了一个无向连通图,它觉得,如果选出一些边来,使得这个图变为一棵树,那么这个边集就非常棒。
现在,Mr. H 想让你帮忙求出有多少个非常棒的边集?
Input
第1行,包含2个整数:n m,表示有n个点m条边。
接下来m行,每行2个整数:u v,表示一条边。
Output
输出1行,包含1个整数,表示方案数模10^9 + 7。
Sample
tcount.in
3 3
1 2
2 3
1 3
tcount.out
3
tcount.in
4 6
1 2
1 3
1 4
2 3
2 4
3 4
tcount.out
16
Note
对于30% 的数据,1 <= n;m <= 12;
对于100% 的数据,1 <= n <= 100, 1 <= m <= n(n-1)/2
数据保证没有重边。
思路:
度数矩阵 a[i][i]为点i的度 其他位置为0
邻接矩阵 a[i][i]=0; a[i][j]=[i与j相连]
基尔霍夫矩阵 = 度数矩阵 - 邻接矩阵
Matrix-Tree 定理:
一个n个点m条边的无向图的生成树总数为其对应的基尔霍夫矩阵的n-1阶余子式(行列式)。
行列式是什么?
一种定义是:
det(A) = Σ (-1)^(i1i2..in) * a1i1 * a2i2 … anin
i1i2..in
其中i1i2…in 是一个1到n的排列,^(i1i2..in) 表示该排列的逆序对个数
行列式的性质
1.某行乘一个数,那么行列式也乘那个数。
2.某行加到另一行,行列式不变
3.交换两行,行列式取反相反数(交换两个数逆序对个数总是改变奇数个)
行列式的计算—高斯消元!
消元的过程中行列式不变,交换一次行列式*-1。所以消元完成后,矩阵只剩下对角线上的主元。
根据行列式的要求,我们要在矩阵中每一行找出且只能找出一个数 每一列找出且只能找出一个数。
那么就是对角线上的数了(只有一种排列),把对角线上的数乘起来就是行列式了。
由于中途有mod,double的除法又有可能炸精度。
所以有两种解决方法,一个是辗转相除,一个是逆元,下面的代码两种都给出来了。
#include <iostream>
#include <cstdio> </