zoukankan      html  css  js  c++  java
  • 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
    ");
               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
    ");
           else printf("No
    ");
        }
        return 0;
    }
    

  • 相关阅读:
    Java核心篇,二十三种设计模式(二),结构型——适配器模式
    Java第三十七天,Mybatis框架系列,基于注解的缓存控制
    Java第三十七天,Mybatis框架系列,缓存
    Java第三十七天,Mybatis框架系列,延迟加载(基于 Collection 的实现方式)
    Java第四十五天,SpringBoot框架系列,SpringBoot基础(五)
    第十一篇 Django 【基础篇】
    第十篇 web应用&http协议
    第八篇 (2)jQuery
    第九篇 BootStrap
    第八篇 JavaScript
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5348421.html
Copyright © 2011-2022 走看看