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 }
View Code
原文地址:https://www.cnblogs.com/gryzy/p/14505816.html