SCL--生成树计数(Matrix-Tree定理)

2015-09-07 20:52:51

总结:2012 多校#1 的 F题遇到的生成树计数,学习一下~

  相关学习资料:周冬论文博客比较好的code

  生成树计数方法较多,然而由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;
}

 

posted @ 2015-09-07 21:44  Naturain  阅读(205)  评论(0编辑  收藏  举报