SCL--生成树计数(Matrix-Tree定理)
2015-09-07 20:52:51
总结:2012 多校#1 的 F题遇到的生成树计数,学习一下~
生成树计数方法较多,然而由Matrix-Tree定理(Kirchhoff矩阵-树定理),我们可以得到一个非常有效率的算法。它首先于1847年被Kirchhoff证明。
适用于无自环、重边。
我们先定义矩阵D为度数矩阵(n×n),D[i][i] = deg(i)(i的度数),D[i][j] = 0(i != j)
以及矩阵G为邻接矩阵(n×n),G[i][j] = 1(i与j之间有边相连),G[i][j] = 0(i与j间无边)。
然后让D矩阵减去G矩阵,得到A矩阵,那么生成树的方案数为A的(n-1)阶主子式的行列式的值。
因为A矩阵的特殊性,所以我们可以用整数形式的消元来求行列式的值。
下面是HDU4305核心代码部分。
注意:在调用Det函数时应该传n-1(代表A矩阵的n-1阶主子式)
int Det(int n){ int A[MAXN][MAXN]; for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) A[i][j] = G[i][j]; int res = 1; for(int i = 1; i <= n; ++i){ for(int j = i + 1; j <= n; ++j){ while(A[j][i]){ int t = A[i][i] / A[j][i]; for(int k = i; k <= n; ++k) A[i][k] = (A[i][k] - A[j][k] * t) % mod; for(int k = i; k <= n; ++k) swap(A[i][k],A[j][k]); res = -res; //行列式换行,值取反 } } if(!A[i][i]) return 0; res = res * A[i][i] % mod; } return (res + mod) % mod; }