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
思路:
求出最小生成树和最大生成树,记录两颗生成树中的白边数量mi和ma
如果区间mi-ma中有斐波那契数则Yes,否则No
注意先判断给定的图连通
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxm=1e5+5;
struct Node{
int a,b,c;
}a[maxm];
bool cmp(Node a,Node b){
return a.c<b.c;
}
int pre[maxm];
int mark[maxm];//mark[i]=1表示i是斐波那契数
int n,m;
void finit(){
mark[1]=mark[2]=1;
int x=1,y=2;
int sum=3;
while(sum<maxm){
mark[sum]=1;
x=y,y=sum,sum=x+y;
}
}
void init(){
for(int i=1;i<=n;i++){
pre[i]=i;
}
}
int ffind(int x){
return pre[x]==x?x:pre[x]=ffind(pre[x]);
}
int mintree(){
init();
int sum=0;
int ans=0;
for(int i=0;i<m;i++){
int x=ffind(a[i].a);
int y=ffind(a[i].b);
if(x!=y){
pre[x]=y;
ans+=a[i].c;
sum++;
if(sum==n-1)break;
}
}
return ans;
}
int maxtree(){
init();
int sum=0;
int ans=0;
for(int i=m-1;i>=0;i--){
int x=ffind(a[i].a);
int y=ffind(a[i].b);
if(x!=y){
pre[x]=y;
ans+=a[i].c;
sum++;
if(sum==n-1)break;
}
}
return ans;
}
signed main(){
finit();
int T;
int cas=1;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init();
for(int i=0;i<m;i++){
scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
int x=ffind(a[i].a);
int y=ffind(a[i].b);
if(x!=y){
pre[x]=y;
}
}
printf("Case #%d: ",cas++);
int sum=0;
for(int i=1;i<=n&&sum<=1;i++){//判断图是否连通
if(pre[i]==i){
sum++;
}
}
if(sum>1){//如果不连通
puts("No");
continue;
}
sort(a,a+m,cmp);
int ma=maxtree();
int mi=mintree();
int ok=0;
for(int i=mi;i<=ma;i++){//直接暴力判断
if(mark[i]){
puts("Yes");
ok=1;
break;
}
}
if(!ok)puts("No");
}
return 0;
}