先黑边优先做一次生成树得到白边的最小值min,再以白边优先做一次生成树得到白边的最大值max,只要min到max之间有Fibonacci数则可以,因为从min到max总可以去掉一条黑边换成一条白边。
#include <stdio.h> #include <string.h> #define maxn 110000 struct edge { int u,v,flag; }e[maxn]; int fib[120]; int p[maxn]; int find(int x) { if(p[x]==x) return x; else return p[x]=find(p[x]); } void link(int a,int b) { int x=find(a); int y=find(b); if(x!=y) p[x]=y; } int main() { int i; int sum,ans; int n,m; int u,v,flag; int Cas=0; int T; int Max,Min; fib[1]=fib[0]=1; for(i=2;i<=30;i++) fib[i]=fib[i-1]+fib[i-2]; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); Cas++; sum=0; for(i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].flag); for(i=1;i<=n;i++) p[i]=i; for(i=1;i<=m;i++) { u=e[i].u,v=e[i].v,flag=e[i].flag; if(find(u)!=find(v)) { link(u,v); sum++; } } if(sum<n-1) { printf("Case #%d: No ",Cas); continue; } sum=0; for(i=1;i<=n;i++) p[i]=i; for(i=1;i<=m;i++) { u=e[i].u,v=e[i].v,flag=e[i].flag; if(flag==0) continue; if(find(u)!=find(v)) { link(u,v); sum++; } } Max=sum; sum=0; for(i=1;i<=n;i++) p[i]=i; for(i=1;i<=m;i++) { u=e[i].u,v=e[i].v,flag=e[i].flag; if(flag==1) continue; if(find(u)!=find(v)) { link(u,v); sum++; } } Min=n-1-sum; ans=0; for(i=0;i<=30;i++) { if(fib[i]<=Max&&fib[i]>=Min) { ans=1; break; } } if(ans==1) printf("Case #%d: Yes ",Cas); else printf("Case #%d: No ",Cas); } return 0; }