noip.ac 3277
题意:N个点M条边,每条边是黑色或者白色。问是否存在某一棵生成树,使得白色边的数量是斐波那契数列中的某一项。
——————————————————————————————————
分两次生成树,一次先取白边,一次先取黑边!两次取得白边的数量之间如果有斐波那契数那么就存在,否则不存在!
注意,给的边数量可能不能生成树!
——————————————————————————————————
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 int n,m; 5 struct edge 6 { 7 int u,v,s; 8 }e[maxn]; 9 bool cmp(edge a,edge b) 10 { 11 return a.s<b.s; 12 } 13 int f[maxn]; 14 int js,mn,mx; 15 int find(int x) 16 { 17 return f[x]==x?x:f[x]=find(f[x]); 18 } 19 void join(int x,int y) 20 { 21 x=find(x);y=find(y); 22 if(rand()%2)f[x]=y; 23 else f[y]=x; 24 } 25 int main() 26 { 27 scanf("%d%d",&n,&m); 28 for(int i=1;i<=m;++i) 29 scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].s); 30 sort(e+1,e+1+m,cmp); 31 for(int i=1;i<=n;++i)f[i]=i; 32 js=0; 33 for(int i=1;i<=m;++i) 34 { 35 if(find(e[i].u)!=find(e[i].v)) 36 { 37 join(e[i].u,e[i].v);js++; 38 if(e[i].s)++mn; 39 if(js==n-1)break; 40 } 41 } 42 if(js!=n-1) 43 { 44 puts("No"); 45 return 0; 46 } 47 for(int i=1;i<=n;++i)f[i]=i; 48 js=0; 49 for(int i=m;i>=1;--i) 50 { 51 if(find(e[i].u)!=find(e[i].v)) 52 { 53 join(e[i].u,e[i].v);js++; 54 if(e[i].s)++mx; 55 if(js==n-1)break; 56 } 57 } 58 if(js!=n-1) 59 { 60 puts("No"); 61 return 0; 62 } 63 int a=0,b=1,c; 64 while(1) 65 { 66 c=a+b;a=b;b=c; 67 if(c>=mn&&c<=mx) 68 { 69 puts("Yes"); 70 break; 71 } 72 else if(c>mx) 73 { 74 puts("No"); 75 break; 76 } 77 } 78 return 0; 79 }