Hdu4786

Fibonacci Tree

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2340    Accepted Submission(s): 748

Problem Description

  Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do some research on Spanning Tree. So Coach Pang decides to solve the following problem:

  Consider a bidirectional graph G with N vertices and M edges. All edges are painted into either white or black. Can we find a Spanning Tree with some positive Fibonacci number of white edges?

(Fibonacci number is defined as 1, 2, 3, 5, 8, ... )

Input

  The first line of the input contains an integer T, the number of test cases.

  For each test case, the first line contains two integers N(1 <= N <= 105) and M(0 <= M <= 105).

  Then M lines follow, each contains three integers u, v (1 <= u,v <= N, u<> v) and c (0 <= c <= 1), indicating an edge between u and v with a color c (1 for white and 0 for black).

Output

  For each test case, output a line “Case #x: s”. x is the case number and s is either “Yes” or “No” (without quotes) representing the answer to the problem.

Sample Input

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

Sample Output

Case #1: Yes
Case #2: No

Source

2013 Asia Chengdu Regional Contest

题意:问构成的生成树当中是否存在黑色边(边为1)数为斐波那契数

思路:求出生成树中最小包括的黑色边数。和最多黑色边数,假设有斐波那契数在两者之间,则能够构成。由于黑白边能够搭配使用

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,m;
int fibo[50];
int f[100010];
struct node
{
    int u,v,c;
} s[100010];

bool cmp1(node x , node y)
{
    return x.c < y.c;
}

bool cmp2(node x, node y)
{
    return  x.c > y.c;
}

int find(int x)
{
    return x == f[x] ? x : f[x] = find(f[x]);
}

void Union(int x ,int y)
{
    int fx = find(x);
    int fy = find(y);

    if(fx != fy)
    {
        f[fx] = fy;
    }
}

int main()
{
#ifdef xxz
    freopen("in.txt","r",stdin);
#endif
    fibo[1] = 1;
    fibo[2] = 2;
    for(int i = 3; ; i++)
    {
        fibo[i] = fibo[i-1] + fibo[i-2];
        if(fibo[i] >= 100000) break;
    }

    int T,Case = 1;;
    scanf("%d",&T);

    while(T--)
    {

        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++) f[i] = i;

        for(int i = 0; i < m; i++)
        {

            scanf("%d%d%d",&s[i].u,&s[i].v,&s[i].c);
            Union(s[i].u,s[i].v);
        }
        int cent = 0;
        int bl = 0, bh = 0;
        int root = 0,size = 0;

        for(int i = 1; i <= n; i++)
        {
            if(f[i] == i)
            {
                cent++;
                root = i;
            }
        }

        printf("Case #%d: ",Case++);
        if(cent >= 2) cout<<"No"<<endl;//首先要推断能否构成一个生成树。推断根节点个数是否为1即可
        else
        {
            sort(s,s+m,cmp1);
            for(int i = 1; i <= n; i++) f[i] = i;

            for(int i = 0; i < m; i++)
            {
                int fu = find(s[i].u);
                int fv = find(s[i].v);
                if(fu == fv) continue;

                bl += s[i].c;
                size++;
                Union(s[i].u,s[i].v);
                if(size == n-1) break;
            }

            size = 0;
            sort(s,s+m,cmp2);
            for(int i = 1; i <= n; i++) f[i] = i;

            for(int i = 0; i < m; i++)
            {
                int fu = find(s[i].u);
                int fv = find(s[i].v);
                if(fu == fv) continue;

                bh += s[i].c;
                size++;
                Union(s[i].u,s[i].v);
                if(size == n-1) break;
            }

            int flag = 0;
            for(int i =1; fibo[i] <= 100000 ; i++ )
            {
                if(fibo[i] >= bl && fibo[i] <= bh)
                {
                    flag = 1;
                    break;
                }
            }
            if(flag) printf("Yes\n");
            else printf("No\n");

        }

    }
}
时间: 2024-10-21 11:45:05

Hdu4786的相关文章

HDU--4786 Fibonacci Tree 生成树+贪心?

N个顶点,M条边,每条边可能为黑色或是白色( 0 or 1 ),问有没有可能用为斐波那契数的数目的白色边构成一棵生成树.所以需要删掉图中的环,根据每次删掉的边有一个白色边的上限和下限,判断一下中间有没有斐波那契数就可以了.实现方法是根据颜色排序,先放黑色边得到的是最小数目的白色边构成的生成树,先放白色边得到是最大数目的白色边构成的生成树. #include<cstring> #include<string> #include<fstream> #include<i

【最小生成树】【kruscal】hdu4786 Fibonacci Tree

假设这张图能够形成具有k条白边的生成树, 则易证k一定形成一个连续的区间[a,b],中间一定不会断开.要是断开--tm怎么可能. 所以求出a,b就好啦,人家都给你把白边赋成1了,直接跑一下最小生成树,再跑一下最大生成树即可咯. #include<cstdio> #include<algorithm> using namespace std; #define N 100010 struct Edge{ int u,v,w; }edges[N]; bool cmp(const Edge

HDU4786 Fibonacci Tree【最小生成树】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4786 题目大意: 给你图的N个点和M条双向边.告诉你每条边的权值.权值为1表示该边是白边,权值为0表示该 边为黑边.问:能否找到一棵生成树,使生成树白边的个数恰好为fibonacci数.如果能构成这样 的fibonacci树,输出Yes,否则输出No. 思路: 先将fibonacci数列打表.然后根据题意构图.然后根据边的权值大小排序,用Kruskal先求一遍 最小生成树,再求一遍最大生成树.如果

hdu4786 Fibonacci Tree (最小生成树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4786 题意:给定图的n个点和m条双向边,告诉你每条边的权值.权值为1表示该边是白边,权值为0表示该边为黑边. 问能否找到一颗生成树,使生成树白边的个数刚好为fibonacci数.如果能构成输出yes,否则输出no. 思路:这里有一个点要知道.因为是0,1 tree.   最小生成树<=生成树的值<=最大生成树.  注意,这个区间的任意一个值都能取到. 但是如果不是0,1 tree,权值就不是任意可

最小生成树练习2(Kruskal)

两个BUG鸣翠柳,一行代码上西天... hdu4786 Fibonacci Tree(生成树)问能否用白边和黑边构成一棵生成树,并且白边数量是斐波那契数. 题解:分别优先加入白边和黑边,求出生成树能包含白边的最大值和最小值,其间有值为斐波那契数即可. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int M=1e5+1; 6 cons

Fibonacci Tree

hdu4786:http://acm.hdu.edu.cn/showproblem.php?pid=4786 题意:给你一个无向图,然后其中有的边是白色的有的边是黑色的.然后问你是否存在一棵生成树,在这课生成树上白色边的数量是一个斐波那契数. 题解:完全没有那样的思想,一道现场水题,就是不会啊,实力太弱 啊.注定打铁啊.这一题是这样的,采用极端思维:就是分别用白色和黑色优先的边去求生成树,得到一个白色数量的区间.这里需要理解的是,白色边的数目,可以在这个区间内变化.也就是构成生成树的白色边的数量