bzoj 1016 最小生成树计数

题目大意:

现在给出了一个简单无向加权图 求这个图中有多少个不同的最小生成树

如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同的

输出方案数对31011的模

思路:

首先我们求出这个最小生成树需要用的边,每种边权的边需要用多少个

然后因为注意到数据很小

可以直接dfs

对于每种权值的边dfs,求出该种权值的边满足最小生成树的方案有多少个

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<cstring>
 7 #include<queue>
 8 #include<map>
 9 #include<vector>
10 #define ll long long
11 #define inf 2147483611
12 #define MAXN 110
13 #define MOD 31011
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;char ch=getchar();
18     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
19     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
20     return x*f;
21 }
22 struct data
23 {
24     int u,v,val;
25     bool operator < (const data &a) const
26     {
27         return val<a.val;
28     }
29 }e[MAXN*20];
30 struct edge {int l,r,num;}g[MAXN*20];
31 int n,m,cnt,f[MAXN],kd,ans,res;
32 void add(int u,int v,int w) {e[++cnt].u=u,e[cnt].v=v,e[cnt].val=w;}
33 int find(int x,bool k)
34 {
35     if(x==f[x]) return x;
36     if(k) return f[x]=find(f[x],1);
37     else return find(f[x],0);
38 }
39 bool ok(int u,int v,int k)
40 {
41     int fa=find(u,k),fb=find(v,k);
42     if(fa==fb) return 1;
43     else {f[fa]=fb;return 0;}
44 }
45 bool kruskal()
46 {
47     cnt=0;
48     for(int i=1;i<=m;i++)
49     {
50         if(e[i].val!=e[i-1].val) g[kd].r=i-1,g[++kd].l=i;
51         if(!ok(e[i].u,e[i].v,1)) cnt++,g[kd].num++;
52     }
53     g[kd].r=m;
54     if(cnt<n-1) return 0;
55     else return 1;
56 }
57 void dfs(int k,int pos,int v)
58 {
59     if(pos==g[k].r+1) {if(v==g[k].num) res++;return ;}
60     int t=find(e[pos].u,0);
61     if(!ok(e[pos].u,e[pos].v,0))
62     {
63         dfs(k,pos+1,v+1);
64         f[t]=t;
65     }
66     dfs(k,pos+1,v);
67 }
68 int main()
69 {
70     n=read(),m=read();
71     int a,b,c;
72     for(int i=1;i<=m;i++) {a=read(),b=read(),c=read();add(a,b,c);}
73     for(int i=1;i<=n;i++) f[i]=i;
74     sort(e+1,e+m+1);
75     if(!kruskal()) {printf("0");return 0;}
76     for(int i=1;i<=n;i++) f[i]=i;
77     ans=1;
78     for(int i=1;i<=kd;i++)
79     {
80         res=0;
81         dfs(i,g[i].l,0);
82         (ans*=res%MOD)%=MOD;
83         for(int j=g[i].l;j<=g[i].r;j++) ok(e[j].u,e[j].v,1);
84     }
85     printf("%d",ans);
86 }
View Code

 

posted @ 2017-11-21 14:22  jack_yyc  阅读(179)  评论(0编辑  收藏  举报