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
Sample Output
题意:
有一个n个点,m条边的图,给定边的权值为1(白色)或2(黑色),问是否存在一个生成树,使得其中白边的数量为斐波那契数?
题解:
首先判断这个图是否为连通图,若不是直接输出No。
然后只要用白边优先(最大生成树)的总权值减去黑边优先(最小生成树)的总权值,就可以得到一个白边数量的区间,然后枚举斐波那契数即可。
#include<bits/stdc++.h> #define MAX 100000 using namespace std; int n,m,p1[MAX+5],p2[MAX+5],fib[55]; struct edge{ int u,v,w; }e[MAX+5]; int find(int r,int p[]) { if(p[r]!=r) p[r]=find(p[r],p); return p[r]; } void init(int p[]) { for(int i=0;i<=MAX;i++) p[i]=i; } bool cmp1(edge a,edge b){return a.w>b.w;} bool cmp2(edge a,edge b){return a.w<b.w;} int KurskalMax(int p[]) { init(p); sort(e,e+m,cmp1); int cnt=0,cost=0,i; for(i=0;i<m;i++) { int fu=find(e[i].u,p),fv=find(e[i].v,p); if(fu!=fv) { p[fu]=fv; cost+=e[i].w; cnt++; } if(cnt==n-1)break; } return cost; } int KurskalMin(int p[]) { init(p); sort(e,e+m,cmp2); int cnt=0,cost=0,i; for(i=0;i<m;i++) { int fu=find(e[i].u,p),fv=find(e[i].v,p); if(fu!=fv) { p[fu]=fv; cost+=e[i].w; cnt++; } if(cnt==n-1)break; } if(cnt!=n-1)return -1; return cost; } int main() { int i; fib[1]=1;fib[2]=2; for(int i=3;i<=40;i++) fib[i]=fib[i-1]+fib[i-2]; int T; scanf("%d",&T); for(int cas=1;cas<=T;cas++) { scanf("%d%d",&n,&m); for(i=0;i<m;i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); e[i].u=u;e[i].v=v;e[i].w=w; } int L=KurskalMin(p1),R=KurskalMax(p2),flag=0; if(L!=-1) { for(i=L;i<=R;i++) { if(fib[lower_bound(fib+1,fib+40+1,i)-fib]==i) { flag=1; break; } } } printf("Case #%d: ",cas); if(flag)printf("Yes "); else printf("No "); } return 0; }