【模板】矩阵树定理-生成树计数

参考博客

Matrix-Tree 定理作用:给定 n 个点 m 条边的无向图,求图的生成树个数。

定义矩阵K[i][j]=D[i][j]-A[i][j],(其中D为度数矩阵(即当i==j时,D[i][j]=节点 i 的度数,其余为0),A为邻接矩阵,有边相邻即为1,其余为0)

结论:对于已经得出的基尔霍夫矩阵,去掉其随意一行一列得出的矩阵的行列式,其绝对值为生成树的个数

注:行列式的绝对值:先用高斯消元消成上三角矩阵,把对角线乘起来

文章:https://wenku.baidu.com/view/872eb02de2bd960590c677c6.html

#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const double eps = 1e-6;
const ll inf = 0x3f3f3f3f;
const ll N = 2e5 + 10;

ll mat[110][110];

ll gauss(ll n){
    ll ans = 1;
    for (ll i = 1; i < n;i++){
        for (ll j = i + 1; j < n; j++) {
            while(mat[j][i]){
                ll t = mat[i][i] / mat[j][i];
                for (ll k = i; k < n;k++){
                    mat[i][k] = (mat[i][k] - t * mat[j][k] + mod) % mod;
                }
                swap(mat[i], mat[j]);
                ans = -ans;
            }
        }
        ans = (ans * mat[i][i]) % mod;
    }
    return (ans + mod) % mod;
}

int main(){
    ll n,m;
    scanf("%lld%lld", &n, &m);
    for (ll i = 1;i<=m;i++){
        ll u,v;
        scanf("%lld%lld", &u, &v);
        mat[u][u]++, mat[v][v]++;
        mat[u][v]--, mat[v][u]--;
    }
    ll num = gauss(n);
    printf("%lld\n",num);
    return 0;
}
posted @ 2020-08-08 10:39  Valk3  阅读(117)  评论(0编辑  收藏  举报