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
Case #1: Yes Case #2: No
题意:有一个图只存在白边和黑边,现在要求一个生成树,问生成树的白边的数量是否可以是一个斐波拉契数。
思路:将所有白边优先建最小生成树得到白边的最多数,在将所有黑边优先建最小生成树,得到白边的最少数,然后在这个区间看是否存在斐波那契数。(图要联通,不连通直接No)
#include <iostream> #include <stdio.h> #include <stdlib.h> #include<string.h> #include<algorithm> #include<math.h> #include<queue> using namespace std; const int N=100010; typedef long long ll; int m,n; struct data { int a,b,w; } tu[N]; int f[N]; bool cmp1(data a,data b) { return a.w>b.w; } bool cmp2(data a,data b) { return a.w<b.w; } int fa(int x) { if(x!=f[x]) return f[x]=fa(f[x]); return f[x]; } int main() { int t,o=1; cin>>t; while(t--) { scanf("%d%d",&n,&m); for(int i=0; i<m; i++) scanf("%d%d%d",&tu[i].a,&tu[i].b,&tu[i].w); sort(tu,tu+m,cmp1); for(int i=1; i<=n; i++) f[i]=i; int l=0; for(int i=0; i<m; i++) { int f1=fa(tu[i].a),f2=fa(tu[i].b); if(f1!=f2) { f[f1]=f2; if(tu[i].w==1)l++; } } sort(tu,tu+m,cmp2); for(int i=1; i<=n; i++) f[i]=i; int r=0; for(int i=0; i<m; i++) { int f1=fa(tu[i].a),f2=fa(tu[i].b); if(f1!=f2) { f[f1]=f2; if(tu[i].w==1)r++; } } if(r<l)swap(l,r); int ff=fa(1),flag=1; for(int i=2; i<=n; i++) if(fa(i)!=ff) { flag=0; break; } if(!flag) printf("Case #%d: No\n",o++); else { int f0=0,f1=1,f2; for(int i=0;; i++) { f2=f1+f0; if(f2>=l&&f2<=r) { printf("Case #%d: Yes\n",o++); break; } else if(f2>r) { printf("Case #%d: No\n",o++); break; } f0=f1,f1=f2; } } } return 0; }