基尔霍夫定理 Kirchhoff's Matrix-Tree Theorem
生活随笔
收集整理的這篇文章主要介紹了
基尔霍夫定理 Kirchhoff's Matrix-Tree Theorem
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
推薦博客: 基爾霍夫定理
直觀應用: 給定一個無向圖/有向圖G,求它生成樹的個數t(G)
可以運用高斯消元求矩陣行列式(高斯消元法有待學習)
例題: HDU 6064 RXD and numbers
題解博客:??? RXD and numbers 題解
code:
#include<bits/stdc++.h> using namespace std; typedef long long (ll); const int mod = 998244353; const int maxn = 1e6; int tempa[405][405];//度矩陣 int tempb[405][405];//鄰接矩陣 int Mat[405][405]; ll inv[maxn]; int in[405]; int out[405]; bool dance; //行列式求值模版 n^3 int solve(int A[405][405], int n){int ans = 1;dance = 0;int i, j, k ;for(i=1; i<=n; i++){for(j=i+1; j<=n; j++){int x=i, y=j;while(A[y][i]){ll t = A[x][i]/A[y][i];for(k=1; k<=n; k++){A[x][k] = (A[x][k] - t*A[y][k])%mod;}swap(x, y);}if(x!=i){dance^=1;for(int k=1; k<=n; k++) swap(A[i][k], A[x][k]);}}ans*=A[i][i];if(ans==0) return 0;ans %= mod;}if(dance) ans = ans*(-1);ans = ans%mod;ans+=mod;ans=ans%mod;return ans; }//階乘計算 ll fact(ll n){ll ans = 1;for(int i=1; i<=n; i++){ans*=i;ans%=mod;}return ans; } // 非階乘的除法逆元 ll exgcd(ll a, ll b, ll &x, ll &y){ if(b==0) {x = 1;y = 0;return a;}ll d = exgcd(b, a%b, y, x);y-=a/b*x;return d; } //階乘除法逆元 void init(){inv[1] = 1;for(int i=2; i<maxn; i++){inv[i] = (mod-mod/i)*inv[mod%i]%mod;}inv[0]=1;for(int i=1; i<maxn; i++){inv[i] = inv[i]*inv[i-1]%mod;}return; } int main(){init();int n, i, j, k;int cas=1;while(~scanf("%d", &n)){int ans[405][405];int a[405][405];memset(Mat, 0, sizeof(Mat));memset(tempa, 0, sizeof(tempa));memset(tempb, 0, sizeof(tempb));memset(in, 0, sizeof(in));memset(out, 0, sizeof(out));for(i=0;i<n;i++){for(j=0; j<n; j++){scanf("%d", &a[i][j]);tempb[i][j]+=a[i][j];//重邊=>故累加 in[j]+=a[i][j];//入度 out[i]+=a[i][j];//出度 }}int ok=1;for(i=0; i<n; i++){tempa[i][i]=in[i];//有向圖,基爾霍夫矩陣的度矩陣為入度 if(in[i]!=out[i]){ //入度不等于出度 ok=0;break;}}if(!ok) { printf("Case #%d: %lld\n", cas++, 0);continue;}for(i=0; i<n; i++){ //計算基爾霍夫矩陣 度矩陣-鄰接矩陣 for(j=0; j<n; j++){Mat[i][j] = tempa[i][j] - tempb[i][j];}}for(i=1; i<n; i++){ //去掉第1行第1列 for(j=1; j<n; j++){ans[i][j] = Mat[i][j];}} ll sum = solve(ans, n-1);sum = sum*fact(in[0])%mod;for(i=1; i<n; i++){sum = sum*fact(in[i]-1);sum%=mod;}for(i=0; i<n; i++){for(j=0; j<n; j++){sum = sum*inv[a[i][j]]%mod;}}printf("Case #%d: %lld\n", cas++, sum);}return 0; }
總結
以上是生活随笔為你收集整理的基尔霍夫定理 Kirchhoff's Matrix-Tree Theorem的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【资源分享】高俊峰老师作品《linux集
- 下一篇: win10关闭远程端口