生成树计数模板 spoj 104 (不用逆元的模板)

 1 /*
 2 这种题,没理解,只是记一记如何做而已;
 3 生成树的计数--Matrix-Tree定理
 4 
 5 题目:SPOJ104(Highways)
 6 题目大意:
 7  *一个有n座城市的组成国家,城市1至n编号,其中一些城市之间可以修建高速公路;
 8  *需要有选择的修建一些高速公路,从而组成一个交通网络;
 9  *计算有多少种方案,使得任意两座城市之间恰好只有一条路径;
10  
11  步骤: 先按输入数据建图:C[u][v]=C[v][u]=-1;degree[u]++; degree[v]++;
12         再去掉一行一列,用计算行列式的某个方法去计算就好了。。
13 */
14 
15 #include<bits/stdc++.h>
16 using namespace std;
17 const int N=15;
18 typedef long long LL;
19 int degree[N];
20 LL C[N][N];
21 LL det(LL a[][N],int n){
22     LL ret=1;
23     for(int i=1; i<n; i++){    //从一开始,去掉了0这一列;
24         for(int j=i+1; j<n; j++)
25             while(a[j][i]){
26                 LL t=a[i][i]/a[j][i];
27                 for(int k=i; k<n; k++)
28                     a[i][k]=(a[i][k]-a[j][k]*t);
29                 for(int k=i; k<n; k++)
30                     swap(a[i][k],a[j][k]);
31                 ret=-ret;
32             }
33         if(a[i][i]==0)return 0;
34         ret=ret*a[i][i];
35     }
36     if(ret<0)ret=-ret;
37     return ret;
38 }
39 int main(){
40     int tcase;cin>>tcase;
41     while(tcase--){
42         memset(degree,0,sizeof(degree));
43         memset(C,0,sizeof(C));
44         int n,m,u,v;
45         scanf("%d%d",&n,&m);
46         while(m--){
47             scanf("%d%d",&u,&v);
48             u--;v--;
49             C[u][v]=C[v][u]=-1;
50             degree[u]++;
51             degree[v]++;
52         }
53         for(int i=0; i<n; ++i)
54             C[i][i]=degree[i];
55         printf("%lld\n",det(C,n));
56     }
57     return 0;
58 }
59 /*
60 input:         output:
61 4            8
62 4 5            1
63 3 4            1
64 4 2            3
65 2 3
66 1 2
67 1 3
68 
69 2 1
70 2 1
71 
72 1 0
73 
74 3 3
75 1 2
76 2 3
77 3 1
78 */

 

posted @ 2019-10-16 17:15  古比  阅读(163)  评论(0编辑  收藏  举报