[BZOJ1016][JSOI2008]最小生成树计数 最小生成树 搜索

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1016

做这道题之前需要知道一些结论,同一个图的最小生成树中相同权值的边的个数是不会变的,如果有一种方案中权值为666的边有233条,那么另一种方案一定也是这样,并且它们在图中对连通性的影响也是相同的。

于是我们先求出一种方案,记录下每种权值的边对应的数量。然后把权值相同的边分为一组,对于每一组搜索选出边的合法方案,乘法原理一下答案就出来了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int mod=31011;
 6 int inline readint(){
 7     int Num;char ch;
 8     while((ch=getchar())<'0'||ch>'9');Num=ch-'0';
 9     while((ch=getchar())>='0'&&ch<='9') Num=Num*10+ch-'0';
10     return Num;
11 }
12 int n,m;
13 struct EDGE{
14     int u,v,w;
15 }e[2010],a[1010];
16 int cnt=0,tot=0;
17 bool cmp(EDGE a,EDGE b){
18     return a.w<b.w;
19 }
20 int fa[110];
21 int getfa(int x){
22     return fa[x]==x?x:getfa(fa[x]);
23 }
24 int sum=0;
25 void dfs(int x,int pos,int k){
26     if(pos==a[x].v+1){
27         if(k==a[x].w) sum++;
28         return;
29     }
30     int fu=getfa(e[pos].u),
31         fv=getfa(e[pos].v);
32     if(fu!=fv){
33         fa[fu]=fv;
34         dfs(x,pos+1,k+1);
35         fa[fu]=fu;
36         fa[fv]=fv;
37     }
38     dfs(x,pos+1,k);
39 }
40 int main(){
41     n=readint();
42     m=readint();
43     for(int i=1;i<=m;i++){
44         e[i].u=readint();
45         e[i].v=readint();
46         e[i].w=readint();
47     }
48     sort(e+1,e+1+m,cmp);
49     for(int i=1;i<=n;i++) fa[i]=i;
50     for(int i=1;i<=m;i++){
51         if(e[i].w!=e[i-1].w){
52             a[cnt].v=i-1;
53             a[++cnt].u=i;
54         }
55         int fu=getfa(e[i].u),
56             fv=getfa(e[i].v);
57         if(fu!=fv){
58             fa[fu]=fv;
59             a[cnt].w++;
60             tot++;
61         }
62     }
63     a[cnt].v=m;
64     if(tot!=n-1){
65         puts("0");
66         return 0;
67     }
68     for(int i=1;i<=n;i++) fa[i]=i;
69     int ans=1;
70     for(int i=1;i<=cnt;i++){
71         sum=0;
72         dfs(i,a[i].u,0);
73         ans=ans*sum%mod;
74         for(int j=a[i].u;j<=a[i].v;j++){
75             int fu=getfa(e[j].u),
76                 fv=getfa(e[j].v);
77             if(fu!=fv) fa[fu]=fv;
78         }
79     }
80     printf("%d\n",ans);
81     return 0;
82 }

 

posted @ 2017-09-04 20:35  halfrot  阅读(162)  评论(0编辑  收藏  举报