spoj 104 Highways(Matrix-tree定理)

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
",ans+eps);
44     }
45     return 0;
46 }
原文地址:https://www.cnblogs.com/mjtcn/p/8502826.html