码迷,mamicode.com
首页 > Web开发 > 详细

bzoj 1016 JSOI2008 最小生成树计数

时间:2016-06-11 17:11:14      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
 7 #define maxn 5010
 8 #define INF (1LL<<50)
 9 #define mod 31011
10 
11 using namespace std;
12 typedef long long llg;
13 
14 struct data{
15     int u,v,x;
16     bool operator < (const data &h)const{return x<h.x;}
17 }s[maxn];
18 struct dat1{
19     int l,r,x;
20     dat1(int a=0,int b=0,int c=0):l(a),r(b),x(c){};
21 }ss[maxn];
22 int n,m,fa[maxn],ls,la[maxn],w[maxn];
23 llg ans=INF,a1,now,aa=1;
24 bool ww[maxn];
25 
26 int getint(){
27     int w=0,q=0;
28     char c=getchar();
29     while((c<0||c>9)&&c!=-) c=getchar();
30     if(c==-) q=1,c=getchar();
31     while(c>=0&&c<=9) w=w*10+c-0,c=getchar();
32     return q?-w:w;
33 }
34 
35 int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
36 
37 inline void work(){
38     now=0;int k=0;
39     for(int i=1;i<=n;i++) fa[i]=i;
40     for(int i=1,u,v;i<=m;i++)
41         if(ww[i]){
42             u=s[i].u;v=s[i].v;
43             if(find(u)!=find(v)){
44                 now+=s[i].x; k++;
45                 fa[find(u)]=find(v);
46             }
47     }
48     if(k!=n-1) return;
49     if(now<ans) ans=now,a1=1;
50     else if(now==ans) a1++;
51 }
52 
53 void dfs(int res,int now,int dd){
54     if(now==dd+1){
55         work();return;
56     }
57     if(res){
58         ww[now]=1;
59         dfs(res-1,now+1,dd);
60     }
61     if(dd-now+1>res){
62         ww[now]=0;
63         dfs(res,now+1,dd);
64     }
65 }
66 
67 int main(){
68     n=getint();m=getint();
69     for(int i=1;i<=m;i++){
70         s[i].u=getint();s[i].v=getint();
71         s[i].x=getint();
72     }
73     sort(s+1,s+m+1);
74     for(int i=1;i<=n;i++) fa[i]=i;
75     for(int i=1,u,v;i<=m;i++){
76         w[i]=w[i-1]; ww[i]=1;
77         la[i]=i; u=s[i].u;v=s[i].v;
78         if(s[i-1].x==s[i].x) la[i]=la[i-1];
79         if(find(u)!=find(v)){
80             now+=s[i].x; w[i]++;
81             fa[find(u)]=find(v);
82         }
83         if(la[i]!=i && s[i+1].x!=s[i].x)
84             ss[++ls]=dat1(la[i],i,w[i]-w[la[i]-1]);
85     }
86     for(int i=1;i<=ls;i++){
87         ans=INF;
88         dfs(ss[i].x,ss[i].l,ss[i].r);
89         for(int j=ss[i].l;j<=ss[i].r;j++) ww[j]=1;
90         aa*=a1; aa%=mod;
91     }
92     ans%=mod; aa%=mod;
93     printf("%lld",aa);
94     return 0;
95 }

 

bzoj 1016 JSOI2008 最小生成树计数

标签:

原文地址:http://www.cnblogs.com/lcf-2000/p/5575412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!