BZOJ 1016: [JSOI2008]最小生成树计数

Solution:

Kruskal+并查集+暴搜

对于每一个符合题意的最小生成树,其每一条树边必定满足:①边权值和一定②对于最小生成树上的每一种权值的边,其数量一定

利用条件②,可以在每一种权值中dfs枚举所有情况,利用并查集判断待取边能否加入(因为回溯需要恢复状态,不能路径压缩)

Code:

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 using namespace std;
 5 inline int read()
 6 {
 7     register int f=1,k=0;register char c=getchar();
 8     while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
 9     while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
10     return k*f;
11 }
12 const int maxn=1010,MOD=31011;
13 int n,m,cnt,tot,ans=1,sum,fa[maxn];
14 struct edge{int x,y,v;}e[maxn];
15 struct data{int l,r,v;}a[maxn];
16 int find(int now){return fa[now]==now?now:find(fa[now]);}
17 bool cmp(edge a,edge b){return a.v<b.v;}
18 void dfs(int x,int now,int k)
19 {
20     if (now==a[x].r+1)
21     {
22         if (a[x].v==k)sum++;
23         return;
24     }
25     register int q=find(e[now].x),p=find(e[now].y);
26     if (p!=q)
27     {
28         fa[q]=p;
29         dfs(x,now+1,k+1);
30         fa[p]=p;fa[q]=q;
31     }
32     dfs(x,now+1,k);
33 }
34 int main()
35 {
36     n=read();m=read();
37     for (register int i=1;i<=n;i++)fa[i]=i;
38     for (register int i=1;i<=m;i++)
39     {
40         e[i].x=read();e[i].y=read();e[i].v=read();
41     }
42     sort(e+1,e+1+m,cmp);
43     for (register int i=1;i<=m;i++)
44     {
45         if (e[i].v!=e[i-1].v)a[++cnt].l=i,a[cnt-1].r=i-1;
46         register int p=find(e[i].x),q=find(e[i].y);
47         if (p!=q)
48         {
49             a[cnt].v++;
50             fa[p]=fa[q];
51             tot++;
52         }
53     }
54     a[cnt].r=m;
55     if (tot!=n-1)
56     {
57         printf("0\n");
58         return 0;
59     }
60     for (register int i=1;i<=n;i++)fa[i]=i;
61     for (register int i=1;i<=cnt;i++)
62     {
63         sum=0;
64         dfs(i,a[i].l,0);
65         ans=(ans*sum)%MOD;
66         for (register int j=a[i].l;j<=a[i].r;j++)
67         {
68             register int q=find(e[j].x),p=find(e[j].y);
69             if (p!=q)fa[q]=p;
70         }
71     }
72     printf("%d\n",ans);
73 }
View Code

 

posted @ 2017-10-19 21:36  Michael_Zhuang  阅读(200)  评论(0编辑  收藏  举报