1. 程式人生 > >SPOJ - HIGH Highways(矩陣樹定理)

SPOJ - HIGH Highways(矩陣樹定理)

color mat space ostream pac com print con nbsp

https://vjudge.net/problem/SPOJ-HIGH

題意:

給n個點m條邊,求生成樹個數。

思路:

矩陣樹裸題。

具體的話可以看一下周冬的論文《生成樹的計數及其應用》。

簡單說一下,$A[ ][ ]$為鄰接矩陣,有邊為1(其實也就是邊的個數,有重邊時要註意),無邊為0。$D[ ][ ]$為度數矩陣,$i=j$時為1,否則為0。

$C[ ][ ]$為關聯矩陣,$C[ ][ ]=D[ ][ ]-A[ ][ ]$。

最後解任意n-1階的主子式即可。

 1 #include<iostream>
 2 #include<algorithm>
 3
#include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int
,ll> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn=1000+5; 17 18 int n,m; 19 double C[maxn][maxn]; 20 int A[maxn][maxn],D[maxn][maxn]; 21 22 double Gauss() 23 { 24 for(int k=1; k<=n; k++) //k表示當前行數,因為行數與列數一樣,所以這裏k也代表了列數 25 { 26 int max_r=k; 27 for(int i=k+1
;i<=n;i++) 28 if(fabs(C[i][k]>fabs(C[max_r][k]))) max_r=i; 29 if(C[max_r][k]==0) return 0; //有一列為0,行列式的值必為0 30 if(max_r!=k) 31 { 32 for(int j=k;j<=n;j++) 33 swap(C[k][j],C[max_r][j]); 34 } 35 for(int i=k+1;i<=n;i++) 36 { 37 double tmp=C[i][k]/C[k][k]; 38 for(int j=k;j<=n;j++) 39 C[i][j]-=tmp*C[k][j]; 40 } 41 } 42 double ans=1; 43 for(int i=1;i<=n;i++) ans*=C[i][i]; //化為三角陣後計算主對角線元素乘積 44 ans=fabs(ans); 45 return ans; 46 } 47 48 int main() 49 { 50 //freopen("in.txt","r",stdin); 51 int T; 52 scanf("%d",&T); 53 while(T--) 54 { 55 memset(A,0,sizeof(A)); 56 memset(D,0,sizeof(D)); 57 scanf("%d%d",&n,&m); 58 for(int i=0;i<m;i++) 59 { 60 int u,v; 61 scanf("%d%d",&u,&v); 62 D[u][u]++; D[v][v]++; 63 A[u][v]++; A[v][u]++; 64 } 65 n--; 66 for(int i=1;i<=n;i++) 67 for(int j=1;j<=n;j++) 68 C[i][j]=D[i][j]-A[i][j]; 69 printf("%.0lf\n",Gauss()); 70 } 71 return 0; 72 }

SPOJ - HIGH Highways(矩陣樹定理)