首页 > 代码库 > 矩阵树定理

矩阵树定理

生成树计数问题。

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。

3.G的Kirchhoff矩阵(也称为拉普拉斯算子)C[G]=D[G]-A[G]。

则G的生成树个数等于C[G]任何一个n-1阶主子式的行列式的绝对值。

 

#include<bits/stdc++.h>
using namespace std;

int n,m,k,a[55][55];
long long g[55][55]; 

long long calc()
{
    long long ans = 1;
    for(int i = 1;i < n;i++)
    {
        for(int j = i+1;j < n;j++)
        {
            while(g[j][i] != 0)
            {
                long long t = g[i][i]/g[j][i];
                for(int k = i;k < n;k++)    g[i][k] -= t*g[j][k];
                for(int k = i;k < n;k++)    swap(g[i][k],g[j][k]);
                ans = -ans;
            }
        }
        if(g[i][i] == 0)    return 0;
        ans = ans*g[i][i];
    }
    return abs(ans);
}

int main()
{
    ios::sync_with_stdio(false);
    while(cin >> n >> m >> k)
    {
        memset(a,0,sizeof(a));
        memset(g,0,sizeof(g));
        while(m--)
        {
            int x,y;
            cin >> x >> y;
            a[x][y] = a[y][x] = 1;
        }
        for(int i = 1;i <= n;i++)
        {
            int t = 0;
            for(int j = 1;j <= n;j++)
            {
                if(i != j && !a[i][j])
                {
                    t++;
                    g[i][j] = -1;
                }
            }
            g[i][i] = t;
        }
        cout << calc() << endl;
    }
    return 0;
}

 

矩阵树定理