BZOJ1016 [JSOI2008]最小生成树计数

1.一个图的最小生成树中的某一权值的边的个数是确定的。

2.这些边的作用是确定的。

 1 #include <cstdio>
2 #include <vector>
3 #include <cstring>
4 #include <algorithm>
5 using namespace std;
6 const int maxn = 1005;
7 int fa[105],vis[maxn];
8 const int mod = 31011;
9 struct node{
10     int u,v,w,ans;
11 }a[maxn];
12 vector<int>w[maxn];
13 int x[maxn],p[maxn],xx[maxn];
14 int findf(int x){
15     int rt = x;
16     while(rt!=fa[rt])rt = fa[rt];
17     while(rt!=x){
18         int t = fa[x];
19         fa[x] = rt;
20         x = t;
21     }
22     return rt;
23 }
24 int findd(int x){
25     int rt = x;
26     while(rt!=p[rt])rt = p[rt];
27     while(rt!=x){
28         int t = p[x];
29         p[x] = rt;
30         x = t;
31     }
32     return rt;
33 }
34 bool cmp(node a,node b){
35     return a.w<b.w;
36 }
37 int main()
38 {
39     int n,m;scanf("%d%d",&n,&m);
40     for(int i = 1;i<=m;++i)scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
41     sort(a+1,a+1+m,cmp);
42     int cnt = 0;
43     for(int i = 1;i<=m;++i)
44     {
45         if(a[i].w==a[i-1].w)a[i].ans = a[i-1].ans;
46         else a[i].ans = ++cnt;
47         w[a[i].ans].push_back(i);
48     }
49     int ss = 0;
50     for(int i = 1;i<=n;++i)fa[i] = i;
51     for(int i = 1;i<=m;++i){
52         int fx = findf(a[i].u),fy = findf(a[i].v);
53         if(fx==fy)continue;
54         fa[fx] = fy;
55         xx[a[i].ans]++;
56         ss++;
57     }
58     if(ss!=n-1){printf("0\n");return 0;}
59     for(int i = 0;i<=11;++i)x[i] = 1<<i;
60     for(int i = 1;i<=n;++i)fa[i] = i;
61     int ans = 1;
62     for(int i = 1;i<=cnt;++i){
63         int len = 1<<w[i].size(),sum = 0,kase = 0;
64         for(int j = 1;j<len;++j){
65             int ok = 1,tot = 0;
66             for(int k = 1;k<=n;++k)p[k] = fa[k];
67             for(int k = 0;k<w[i].size();++k)if(j&x[k]){
68                 int fx = findd(a[w[i][k]].u),fy = findd(a[w[i][k]].v);
69                 if(fx==fy){ok = 0;break;}
70                 p[fx] = fy;
71                 tot++;
72             }
73             if(ok&&tot==xx[i])kase = j,sum++;
74         }
75         if(sum)ans = (ans*sum)%mod;
76         if(kase)for(int k = 0;k<w[i].size();++k)if(kase&x[k])
77             fa[findf(a[w[i][k]].u)] = findf(a[w[i][k]].v);
78     }
79     printf("%d\n",ans);
80
81     return 0;
82 }

posted on 2015-08-02 23:23  round_0  阅读(114)  评论(0编辑  收藏

• 随笔 - 116
• 文章 - 0
• 评论 - 0
• 引用 - 0