求出需要白边最少的和最多的生成树...如果在这两个数之间有fibonacci数则说明存在....原理是一个生成树构造成另一个生成树..必定可以不断的去边又加边来完成..所以如果所需白边最少和最多之间有fibonacci数则一定可以通过变换找出来....
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N =100000+10;
int f[28];
bool hash[N*2];
struct node{
int u,v,w;
}edge[N];
int tree[N];
int find(int x)
{
if(tree[x]==-1)
return x;
return tree[x]=find(tree[x]);
}
void init()
{
f[1]=1,f[2]=2;
memset(hash,false,sizeof(hash));
hash[1]=hash[2]=true;
for(int i=3;i<=25;i++)
{
f[i]=f[i-1]+f[i-2];
hash[f[i]]=true;
}
}
int main()
{
int T;
init();
scanf("%d",&T);
for(int kase =1;kase<=T;kase++)
{
int n,m;
int flag=0;
int cnt=0;
scanf("%d%d",&n,&m);
memset(tree,-1,sizeof(tree));
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
edge[i].u=a;
edge[i].v=b;
edge[i].w=c;
}
int ans=0;
for(int i=1;i<=m;i++)
{
int x=find(edge[i].u);
int y=find(edge[i].v);
if(x!=y)
{
ans++;
tree[y]=x;
}
if(ans==n-1)
break;
}
if(ans!=n-1)// 如果不能构成生成树
{
printf("Case #%d: No\n",kase);
continue;
}
else
{
ans=0;
memset(tree,-1,sizeof(tree));
for(int i=1;i<=m;i++)
{
if(edge[i].w==0) continue;
int x=find(edge[i].u);
int y=find(edge[i].v);
if(x!=y)
{
ans++;
tree[y]=x;
}
if(ans==n-1)
break;
}
memset(tree,-1,sizeof(tree));
int ans1=0;
for(int i=1;i<=m;i++)
{
if(edge[i].w==1) continue;
int x=find(edge[i].u);
int y=find(edge[i].v);
if(x!=y)
{
ans1++;
tree[y]=x;
}
if(ans1==n-1)
break;
}
for(int i=n-1-ans1;i<=ans;i++)
{
if(hash[i])
{
flag=1;
break;
}
}
}
if(flag) printf("Case #%d: Yes\n",kase);
else
printf("Case #%d: No\n",kase);
}
return 0;
}