BZOJ 1016 最小生成树计数 【模板】最小生成树计数

【题解】

 1 #include<cstdio>
2 #include<algorithm>
3 using namespace std;
4 const int maxn=2000,Mod=31011;
5 int n,m,tot,sum,ans=1,cnt,st[maxn],fa[maxn],num[maxn];
6 struct edge{int x,y,dis,pos;}e[maxn];
8     k=0; int f=1; char c=getchar();
9     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
10     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
11     k*=f;
12 }
13 int find(int x){return fa[x]==x?x:find(fa[x]);}
14 void dfs(int kind,int now,int chosen){
15     if (now==st[kind+1]){
16         if (chosen==num[kind]) sum++;
17         return;
18     }
19     int p=find(e[now].x),q=find(e[now].y);
20     if (p!=q) fa[p]=q,dfs(kind,now+1,chosen+1),fa[p]=p,fa[q]=q;
21     dfs(kind,now+1,chosen);
22 }
23 bool cmp(edge a,edge b){return a.dis<b.dis;}
24 int main(){
27     sort(e+1,e+m+1,cmp);
28     for (int i=1;i<=m;i++) {
29         if (e[i].dis!=e[i-1].dis) st[++cnt]=i;
30         e[i].pos=cnt;
31     }
32     st[cnt+1]=m+1;
33     for (int i=1;i<=n;i++) fa[i]=i;
34     for (int i=1,x,y;i<=m;i++)
35         if ((x=find(e[i].x))!=(y=find(e[i].y))) fa[x]=y,num[e[i].pos]++,tot++;
36     if (tot!=n-1) return puts("0"),0;
37     for (int i=1;i<=n;i++) fa[i]=i;
38     for (int i=1;i<=cnt;i++) if(num[i]){
39         sum=0; dfs(i,st[i],0);
40         for (int j=st[i];j<st[i+1];j++) fa[find(e[j].x)]=find(e[j].y);
41         ans=1LL*ans*sum%Mod;
42     }
43     printf("%d",ans);
44     return 0;
45 }
View Code
posted @ 2017-10-27 07:47  Driver_Lao  阅读(...)  评论(... 编辑 收藏