标签:
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4136 Accepted Submission(s): 1283
我们等于是要证明对于所有在min和max之间的白边数我们都能够达到。
考虑从最小的min开始,我总可以找到一条黑边,使得将它去掉在补上一条白边保持图联通。为什么呢,如果在某一个状态(设白边数为x)下,不存在一条黑边可以被白边代替,那么现在我们把所有黑边去掉,剩下x条白边,那我们知道,x一定等于max,因为若x<max,那么我们在算max的那个步骤中,先将这x条白边加入,还可以在加入max-x条白边使得不存在环,那么这与没有一条黑边可以被白边代替矛盾,所以这就证明了从min到max我都可以达到
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 using namespace std; 5 struct node 6 { 7 int u,v,c; 8 } N[100005]; 9 int fib[50]; 10 int fa[100005]; 11 int t; 12 int n,m; 13 int coun; 14 int find(int root) 15 { 16 if(root==fa[root]) 17 return root; 18 else 19 return fa[root]=find(fa[root]); 20 } 21 void unin(int a,int b) 22 { 23 int aa=find(a); 24 int bb=find(b); 25 if(aa!=bb) 26 fa[aa]=bb; 27 } 28 void init() 29 { 30 for(int i=1; i<=n; i++) 31 fa[i]=i; 32 } 33 void fi() 34 { 35 fib[1]=1; 36 fib[2]=2; 37 for(int i=3;; i++) 38 { 39 fib[i]=fib[i-1]+fib[i-2]; 40 if(fib[i]>100005) 41 { 42 coun=i; 43 break; 44 } 45 } 46 } 47 int kruscal(int exm) 48 { 49 init(); 50 int k=0; 51 for(int i=1; i<=m; i++) 52 { 53 if(N[i].c!=exm) 54 { 55 if(find(N[i].u)!=find(N[i].v)) 56 { 57 k++; 58 unin(N[i].u,N[i].v); 59 } 60 } 61 } 62 return k; 63 } 64 int main() 65 { 66 fi(); 67 while(scanf("%d",&t)!=EOF) 68 { 69 for(int j=1; j<=t; j++) 70 { 71 scanf("%d %d",&n,&m); 72 for(int i=1; i<=m; i++) 73 scanf("%d %d %d",&N[i].u,&N[i].v,&N[i].c); 74 printf("Case #%d: ",j); 75 int zha; 76 zha=kruscal(2);//可以使用白边和黑边 77 if(zha!=(n-1))//判环 78 { 79 printf("No\n"); 80 continue; 81 } 82 int l=n-1-kruscal(1);//构成生成树的白边数量的下限 83 int r=kruscal(0);// 构成生成树的白边数量的上限 84 int flag=0; 85 for(int i=1; i<coun; i++)//判断是否存在满足条件的fib 86 { 87 if(fib[i]>=l&&fib[i]<=r) 88 { 89 printf("Yes\n"); 90 flag=1; 91 break; 92 93 } 94 } 95 if(flag==0) 96 printf("No\n"); 97 } 98 } 99 return 0; 100 }
HDU 4786 最小生成树变形 kruscal(13成都区域赛F)
标签:
原文地址:http://www.cnblogs.com/hsd-/p/5703032.html