Matrix-Tree定理(Kirchhoff矩阵-树定理)解决简单平凡无向图的生成树计数问题最有力的武器之一
1、G的度数矩阵D[G]是一个n*n的矩阵,并且满足:当i≠j时,dij=0;当i=j时,dij等于vi的度数。
2、G的邻接矩阵A[G]也是一个n*n的矩阵, 并且满足:如果vi、vj之间有边直接相连,则aij=1,否则为0。
我们定义G的Kirchhoff矩阵(也称为拉普拉斯算子)C[G]为C[G]=D[G]-A[G],则Matrix-Tree定理可以描述为:G的所有不同的生成树的个数等于其Kirchhoff矩阵C[G]任何一个n-1阶主子式的行列式的绝对值。所谓n-1阶主子式,就是对于r(1≤r≤n),将C[G]的第r行、第r列同时去掉后得到的新矩阵,用Cr[G]表示。
Cayley定理:完全图的生成树个数为n^(n-2).推论:有根完全图的生成树个数为n^(n-1)
long det(long[][] mat, int n) {
long ans = 1;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++)
while (mat[i][j] != 0) {
long t = mat[i][i] / mat[i][j];
for (int k = 0; k < n; k++)
mat[k][i] -= mat[k][j] * t;
long temp;
for (int k = 0; k < n; k++) {
temp = mat[k][i];
mat[k][i] = mat[k][j];
mat[k][j] = temp;
}
ans = -ans;
}
if (mat[i][i] == 0)
return 0;
}
for (int i = 0; i < n; i++)
ans *= mat[i][i];
return ans;
}
void run() {
int n = scan.nextInt();
int m = scan.nextInt();
long map[][] = new long[n][n];
while (m-- > 0) {
int a = scan.nextInt() - 1;
int b = scan.nextInt() - 1;
if (map[a][b] == -1)
continue;
map[a][b]--;
map[b][a]--;
map[a][a]++;
map[b][b]++;
}
System.out.println(det(map, n - 1));
}