# BZOJ 1016 最小生成树计数

http://www.lydsy.com/JudgeOnline/problem.php?id=1016

  1 #include<algorithm>
2 #include<cstdio>
3 #include<cmath>
4 #include<cstring>
5 #include<iostream>
6 #include<vector>
7 const int Mod=31011;
8 const double eps=1e-6;
9 std::vector<int>v[115];
10 struct edge{
11     int u,v,w;
12 }e[200005];
13 int fa[115],Fa[115],n,m,vis[115];
14 int c[115][115],g[115][115];
16     char ch=getchar();int t=0,f=1;
17     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
18     while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
19     return t*f;
20 }
21 bool cmp(edge a,edge b){
22     return a.w<b.w;
23 }
24 int find(int x,int f[]){
25     if (f[x]==x) return x;
26     else return find(f[x],f);
27 }
28 int sgn(double x){
29     if (x<-eps) return -1;
30     if (x>eps) return 1;
31     return 0;
32 }
33 int gauss(int a[][115],int n){
34     int res=1;
35     for (int i=1;i<=n;i++)
36      for (int j=1;j<=n;j++)
37       a[i][j]%=Mod;
38     for (int i=1;i<=n;i++){
39         for (int j=i+1;j<=n;j++)
40          while (a[j][i]){
41                 int t=a[i][i]/a[j][i];
42                 for (int k=i;k<=n;k++)
43                  a[i][k]=(a[i][k]-t*a[j][k])%Mod;
44                 for (int k=i;k<=n;k++)
45                  std::swap(a[i][k],a[j][k]);
46                 res=-res;
47          }
48         if (a[i][i]==0) return 0;
49         res=(res*a[i][i])%Mod;
50     }
51     if (res<0) res=-res;
52     res=(res+Mod)%Mod;
53     return res;
54 }
55 int main(){
57     memset(g,0,sizeof g);
58     for (int i=1;i<=n;i++)
59      v[i].clear();
60     for (int i=1;i<=m;i++){
62     }
63     int ans=1;
64     for (int i=1;i<=n;i++) fa[i]=i,vis[i]=0;
65     std::sort(e+1,e+1+m,cmp);
66     e[0].w=e[1].w;
67     int Edge=-1;
68     for (int i=1;i<=m+1;i++){
69         if (i==m+1||e[i].w!=Edge){
70             for (int j=1;j<=n;j++)
71              if (vis[j])
72               v[find(j,Fa)].push_back(j),vis[j]=0;
73             for (int j=1;j<=n;j++)
74              if (v[j].size()>1){
75               for (int k=1;k<=n;k++)
76                for (int l=1;l<=n;l++)
77                 c[k][l]=0;
78               int len=v[j].size();
79               for (int a=0;a<len;a++)
80                for (int b=a+1;b<len;b++){
81                     int a1=v[j][a],b1=v[j][b];
82                     c[a+1][b+1]=(c[b+1][a+1]-=g[a1][b1]);
83                     c[a+1][a+1]+=g[a1][b1];
84                     c[b+1][b+1]+=g[a1][b1];
85                }
86               int res=(int)gauss(c,len-1);
87               ans=(ans*res)%Mod;
88               for (int a=0;a<len;a++)
89                 fa[v[j][a]]=j;
90              }
91             for (int j=1;j<=n;j++){
92                 v[j].clear();
93                 Fa[j]=fa[j]=find(j,fa);
94             }
95             if (i==m+1) break;
96             Edge=e[i].w;
97         }
98         int u=e[i].u,v=e[i].v;
99         int u1=find(u,fa),v1=find(v,fa);
100         if (u1==v1) continue;
101         vis[u1]=vis[v1]=1;
102         Fa[find(u1,Fa)]=find(v1,Fa);
103         g[u1][v1]++;
104         g[v1][u1]++;
105     }
106     int U=find(1,fa);
107     for (int i=2;i<=n;i++)
108      if (U!=find(i,fa)) {
109             puts("0");
110             return 0;
111     }
112     if (m<n-1){
113         puts("0");
114         return 0;
115     }
116     printf("%d\n",ans);
117 }

posted @ 2016-06-14 08:28  GFY  阅读(...)  评论(... 编辑 收藏