矩阵树 Matrix-Tree 定理实现模板(高斯消元求解行列式)

大佬1博客:https://www.cnblogs.com/zj75211/p/8039443.html

大佬2博客:https://www.cnblogs.com/yangsongyi/p/10697176.html

三个定理:

  1. 给出无向图,求这个图的生成树个数
  2. 给出有向图和其中的一个点,求以这个点为根的生成外向树个数
  3. 给出有向图和其中一个点,求以这个点为根的生成内向树个数

对于上述三个定理,首先都是需要构造基尔霍夫Kirchhoff矩阵,构造方法如下:

基尔霍夫Kirchhoff矩阵 K = 度数矩阵 D - 邻接矩阵 A

对于上述三个定理,分别求解:

  1. D矩阵:度数,A矩阵:无向图,删除任意第 r 行和第 r 列后的行列式的绝对值即为答案
  2. D矩阵:入度,A矩阵:有向图,假设点为 x ,则删除第 x 行和第 x 列后的行列式的绝对值即为答案
  3. D矩阵:出度,A矩阵:有向图,假设点为 x ,则删除第 x 行和第 x 列后的行列式的绝对值即为答案

最后挂个高斯消元求解行列式的模板,时间复杂度为 n^3 ,空间复杂度为 n^2,允许取模

代码:

const int N=110;

const int mod=998244353;

LL a[N][N];

LL q_pow(LL a,LL b)
{
    LL ans=1;
    while(b)
    {
        if(b&1)
            ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return ans;
}

LL Gauss(int n)
{
    LL ans=1;
    for(int i=2;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
            if(!a[i][i]&&a[j][i]) 
            {
                ans=-ans;
                swap(a[i],a[j]);
                break;
            }
        LL inv=q_pow(a[i][i],mod-2);
        for(int j=i+1;j<=n;j++)
        {
            LL temp=a[j][i]*inv%mod;
            for(int k=i;k<=n;k++)
                a[j][k]=(a[j][k]-a[i][k]*temp%mod+mod)%mod;
        }
        ans=ans*a[i][i]%mod;
    }
    return ans;
}

 

你可能感兴趣的:(数论)