Fibonacci Tree
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4136 Accepted Submission(s): 1283
Problem Description
Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do some research on Spanning Tree. So Coach Pang decides to solve the following problem:
Consider a bidirectional graph G with N vertices and M edges. All edges are painted into either white or black. Can we find a Spanning Tree with some positive Fibonacci number of white edges?
(Fibonacci number is defined as 1, 2, 3, 5, 8, ... )
Input
The first line of the input contains an integer T, the number of test cases.
For each test case, the first line contains two integers N(1 <= N <= 105) and M(0 <= M <= 105).
Then M lines follow, each contains three integers u, v (1 <= u,v <= N, u<> v) and c (0 <= c <= 1), indicating an edge between u and v with a color c (1 for white and 0 for black).
Output
For each test case, output a line “Case #x: s”. x is the case number and s is either “Yes” or “No” (without quotes) representing the answer to the problem.
Sample Input
2
4 4
1 2 1
2 3 1
3 4 1
1 4 0
5 6
1 2 1
1 3 1
1 4 1
1 5 1
3 5 1
4 2 1
Sample Output
Case #1: Yes
Case #2: No
Source
2013 Asia Chengdu Regional Contest
题意:N个顶点,M条边,每条边或为白色或为黑色( 1 or 0 ),问有没有用是斐波那契数的数目的白色边构成一棵生成树
题解:N个顶点构成的生成树有N-1条边 ,首先判断能否能构成生成树,图是否是联通的,无法构成则输出No
先使用所有的黑边 不断加边,看最多能使用多少条黑边使得不形成环 求得白边的使用的数量的下界
然后再使用所有的白边,不断的加边,看最多能使用多少条白边使得不形成环,求得白边使用的数量的上界
然后是否存在斐波那契数载这个区间
我们等于是要证明对于所有在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 }