hdu 4786 Fibonacci Tree
Posted phlsheji
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4786 Fibonacci Tree相关的知识,希望对你有一定的参考价值。
题目:大致的意思就是说给定n个点和m条边,这m条边分成两种颜色----白色和黑色,问是否可以形成一个生成树使得白色边的个数是一个斐波那契数。
思路:求出白色边能形成的联通图(非环)的最多边数和最少边数。最大数能够用白边的并查集求得(max=num)。而最少边数能够用黑边的并查集求的(min=n-1-num)。然后再看在min--max之间是否存在斐波那契数就能够了。
解释:为什么这样求联通图的白边的个数区间是对的呢?首先上限就不用说了。那么我们想如果这个图可以形成生成树,这颗树里面除了白边就是黑边,看下边这两个图。
那么我们能够看到白边的最大个数是6,黑边也是6,那么白边的范围就是[3,6],怎么实现呢?我们能够看到要想形成生成树,能够在最大白边的基础上去掉一些白边。用黑边来填充,那么这些白边就是4-7,5-7,6-7。这个图看起来有些特殊啊由于同一时候两边都有4-7,5-7,6-7。
那么白边的图我们换一个
此时我们能够看到白边图和黑边图不再存在同样边不同色的边了。那么此时我们能够通过连接黑7和白7构成生成树。当然存在反复点,那么我们就能够去掉黑4-7或4-10,黑5-7或白5-10,黑6-7或白6-10,那么这样即可成了白边[3-6]的区间。
此时,证明完成。
代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; int t[30]; int f[100010]; int ik; int n,m; struct node { int l,r,c; }c[100010]; void init() { t[1]=1; t[2]=2; for(ik=3;t[ik-1]<=100000;ik++) { t[ik]=t[ik-1]+t[ik-2]; } } int look(int x) { if(x!=f[x]) f[x]=look(f[x]); return f[x]; } int solve(int col) { int x,y,num=0; for(int i=1;i<=n;i++) f[i]=i; for(int i=0;i<m;i++) if(c[i].c!=col) { x=look(c[i].l),y=look(c[i].r); if(x!=y) { f[x]=y; num++; } if(num==n-1) return n-1; } return num; } int main() { int tt; scanf("%d",&tt); int cas=1; init(); while(cas<=tt) { cin>>n>>m; for(int i=0;i<m;i++) { scanf("%d%d%d",&c[i].l,&c[i].r,&c[i].c); } printf("Case #%d: ",cas++); int num=0; num=solve(2); if(num!=n-1) { printf("No\n"); continue; } int ma=solve(0); int mi=n-1-solve(1); bool flag=false; for(int i=1;i<ik;i++) { if(t[i]>=mi&&t[i]<=ma) { flag=true; break; } } if(flag) printf("Yes\n"); else printf("No\n"); } return 0; }
以上是关于hdu 4786 Fibonacci Tree的主要内容,如果未能解决你的问题,请参考以下文章
HDU 4786 Fibonacci Tree(生成树,YY乱搞)
hdu4786 Fibonacci Tree (最小生成树)