1. 程式人生 > >spoj 104 Highways(Matrix-tree定理)

spoj 104 Highways(Matrix-tree定理)

www. nbsp clu tree tex frame 無向圖 之間 tom

spoj 104 Highways

生成樹計數,matrix-tree定理的應用。

Matrix-tree定理:

D為無向圖G的度數矩陣(D[i][i]是i的度數,其他的為0),A為G的鄰接矩陣(若u,v之間存在邊,A[u][v]=A[v][u]=1),C=D-A。

對於一個無向圖G,它的生成樹個數等於其Kirchhoff矩陣任何一個n-1階主子式的行列式的絕對值。 所謂n-1階主子式,就是對於任意一個r,將C的第r行和第r列同表示時刪去後的新矩陣,表示為Cr。

求行列式的值:

把矩陣用高斯消元消成上三角矩陣,對角線的積就是行列式的值。

 1 #include<cstdio>
 2
#include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<cmath> 6 7 using namespace std; 8 9 const double eps = 1e-15; 10 11 double c[20][20]; 12 int T,n,m; 13 14 double Gauss() { 15 for (int k=1; k<=n; ++k) { 16 int r = k;
17 for (int i=k+1; i<=n; ++i) 18 if (fabs(c[i][k]) > fabs(c[r][k])) r = i; 19 if (r!=k) for (int j=1; j<=n; ++j) swap(c[k][j],c[r][j]); 20 for (int i=k+1; i<=n; ++i) 21 if (fabs(c[i][k]) > eps) { 22 double t = c[i][k] / c[k][k];
23 for (int j=k; j<=n; ++j) c[i][j] -= t*c[k][j]; 24 } 25 } 26 double ans = 1.0; 27 for (int i=1; i<=n; ++i) ans = ans*c[i][i]; //矩陣的對角線乘積 28 return (ans > 0) ? ans : -ans;//取絕對值 29 } 30 31 int main() { 32 scanf("%d",&T); 33 while (T--) { 34 memset(c,0,sizeof(c)); 35 scanf("%d%d",&n,&m); 36 for (int u,v,i=1; i<=m; ++i) { 37 scanf("%d%d",&u,&v); 38 c[u][v] = c[v][u] = -1;// 39 c[u][u] ++;c[v][v] ++;//度數 40 } 41 n--; // 去掉最後一行最後一列 42 double ans = Gauss(); //高斯消元 43 printf("%.0lf\n",ans+eps); 44 } 45 return 0; 46 }

spoj 104 Highways(Matrix-tree定理)