MatrixTree速成

前言

MatrixTree定理是用來解決生成樹計數問題的有利工具ios

好比說這道題算法

MatrixTree定理的算法流程也很是簡單工具

咱們記矩陣\(A\)爲無向圖的度數矩陣
記矩陣\(D\)爲無向圖的鄰接矩陣spa

\(A\)矩陣是除了對角線以外各個點值都爲\(0\)的矩陣,\(A[i][i]\)表示\(i\)號點的度數code

\(D\)矩陣記錄兩點之間的度數,\(D[i][j]\)表示\(i\)號點與\(j\)號點之間的邊數get

MatrixTree定理

咱們記矩陣\(G=A-D\)
那麼\(G\)的全部不一樣生成樹的個數等於\(G\)的任何一個 \(n-1\) 階主子式的行列式的絕對值string

實現

MatrixTree定理的實現很是簡單io

  1. 計算出\(G\)矩陣
  2. 後對其進行高斯消元
  3. 把消元后的矩陣的對角線乘起來
  4. 輸出

代碼

就是上面那道題目的代碼class

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN=3001;
const double eps=1e-12;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
double G[MAXN][MAXN],a[MAXN][MAXN];
char s[MAXN][MAXN];
int xx[5]={0,-1,+1,0,0};
int yy[5]={0,0,0,-1,+1};
int N,M;
int dcmp(int x)
{
    if(x<=eps||x>=-eps) return 0;
    else return x<0?-1:1;
}
void Gauss()
{
    N--;
    for(int i=1;i<=N;i++)//每一行 
    {
        int mx=i;
        for(int j=i+1;j<=N;j++)//下面的每一行 
            if(dcmp(G[mx][i]-G[j][i])<0) mx=j;
        if(mx!=i) swap(G[i],G[mx]);
        if(!G[i][i]) {printf("0\n");return ;}
        for(int j=i+1;j<=N;j++)
        {
            double t=G[j][i]/G[i][i];
            for(int k=i;k<=N+1;k++)
                G[j][k]-=t*G[i][k];
        }
    }
    double ans=1;
    for(int i=1;i<=N;i++) ans=ans*G[i][i];
    printf("%.0f\n",abs(ans));
}
int main()
{  
    int T=read();
    while(T--)
    {
        memset(G,0,sizeof(G));
        N=read(),M=read();
        for(int i=1;i<=M;i++)
        {
            int x=read(),y=read();
            G[x][x]++;G[y][y]++;
            G[x][y]--;G[y][x]--;
        }
        Gauss();  
    }
    return 0;  
}
相關文章
相關標籤/搜索