http://acm.hdu.edu.cn/showproblem.php?pid=4786
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
解题思路:
按边的颜色排序两次,一次黑边优先,利用并查集构造一个生成树,此时是所有方法中白边最少的情况,x。而后白边优先,得出的是白边最多的情况,y。找找x,y二者之间是否包括一个Fibonacci数即可。
#include <string.h> #include <stdio.h> #include <iostream> #include <algorithm> //#define debug using namespace std; struct note { int u,v,c; } edge[100005]; int n,m,fa[100005],num; bool cmp1(note a,note b) { return a.c<b.c; } bool cmp2(note a,note b) { return a.c>b.c; } void initset() { for(int i=0; i<=n; i++) fa[i]=i; } int find(int x) { if(x==fa[x]) return x; return fa[x]=find(fa[x]); } int un(int x,int y) { x=find(x); y=find(y); if(x!=y) { fa[y]=x; num++; return 1; } return 0; } int a[1005]; void fib() { a[0]=1; a[1]=1; for(int i=2; i<30; i++) a[i]=a[i-1]+a[i-2]; #ifdef debug printf("%d\n",a[29]); #endif // debug } int main() { int T,tt=0; scanf("%d",&T); fib(); while(T--) { scanf("%d%d",&n,&m); for(int i=0; i<m; i++) scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].c); initset(); sort(edge,edge+m,cmp1); int cnt1; num=0; int count=0; for(int i=0; i<m; i++) { if(un(edge[i].u,edge[i].v)) count+=edge[i].c; if(num==n-1) { cnt1=count; break; } } initset(); sort(edge,edge+m,cmp2); int cnt2; num=0; count=0; for(int i=0; i<m; i++) { if(un(edge[i].u,edge[i].v)) count+=edge[i].c; if(num==n-1) { cnt2=count; break; } } int flag=0; for(int i=0; i<29; i++) if(cnt1==a[i]||cnt2==a[i]) { printf("Case #%d: Yes\n",++tt); flag=1; break; } if(flag) continue; int x=upper_bound(a,a+29,cnt1)-a; int y=upper_bound(a,a+29,cnt2)-a; if(x==y) printf("Case #%d: No\n",++tt); else printf("Case #%d: Yes\n",++tt); } return 0; }