标签:des style blog http io color ar os sp
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
题意:给你些边跟它的权值,权值只能是0或者1,要你求出一颗生成树,使得该树的白边的边数为斐波那契数列,白边的权值为1.
思路:我们可以求出需要最小的白边跟最多的白边,又因为生成树的边比较特殊,权值为0,1 所以我们只需要求出最大生成树,便是需要的最多白边数,求出最小生成树,则为需要的最少白边树。然后只需要判断白边数的区间是否有斐波那契数就可以了,其它的边替换为黑边就可以了
本题还有一个坑点,那就是树本身不连通那么就输出No
AC代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int f[100005]; struct p { int u,v,w; }num[100005]; int a[40]; int n,m; int cnt; bool cmp1(p x,p y) { return x.w<y.w; } bool cmp2(p x,p y) { return x.w>y.w; } int find(int x) { if(x!=f[x]) f[x]=find(f[x]); return f[x]; } int kra() { int i,tot=n; int sum=0; for(i=0;i<cnt;i++) { int x=find(num[i].u); int y=find(num[i].v); if(x==y) continue; f[x]=y; sum+=num[i].w; tot--; if(tot==0)break; } return sum; } int main() { int i,j; int t; a[1]=1; a[2]=2; for(i=3;i<=25;i++) a[i]=a[i-2]+a[i-1]; scanf("%d",&t); int tot=1; while(t--) { scanf("%d %d",&n,&m); for(i=1;i<=n;i++) f[i]=i; cnt=0; for(i=1;i<=m;i++) { int a,b,c; scanf("%d %d %d",&a,&b,&c); num[cnt].u=a; num[cnt].v=b; num[cnt++].w=c; } sort(num,num+cnt,cmp2); int ran1=kra(); for(i=1;i<=n;i++) f[i]=i; sort(num,num+cnt,cmp1); int ran2=kra(); bool ff = true; for(int i = 1;i <= n;i++) if(find(i) != find(1)) { ff = false; break; } if(!ff) { printf("Case #%d: No\n",tot++); continue; } int flag=0; for(i=1;i<25;i++) if(a[i]>=ran2&&a[i]<=ran1) flag=1; if(flag) printf("Case #%d: Yes\n",tot++); else printf("Case #%d: No\n",tot++); } return 0; }
标签:des style blog http io color ar os sp
原文地址:http://blog.csdn.net/u012313382/article/details/41099669