HDU 4786 Fibonacci Tree 并查集+生成树=kruskal

Fibonacci Tree

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

Total Submission(s): 2149    Accepted Submission(s): 682

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

这题要求生成树的 边权和 为 斐波那契值;

一个生成树构造成另一个生成树,可以不断的去边又加边来完成。 而这题全部边权为01,所以加边去边过程是+1 +1 的;

可以求出生成树 最大边权和 ,及最小的边权和。  然后枚举24个 小于100000的斐波那契数。

只要有某个斐波那契数  fb,    fb<=最大边权和&&fb>=最小边权和  那就是可以构成这样一颗树的;

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int f[100100];
int tt[25];
int find(int x){return x==f[x]?x:f[x] = find(f[x]);}  //初始化为自己
void Union(int x, int y){
    int fx = find(x), fy = find(y);
    if(fx == fy)return ;
    if(fx>fy) swap(fx,fy);
    f[fx] = f[x] = f[y] = fy;//这样 就可以直接查f[i]  判断祖先了
}
struct path
{
    int v,u,c;
};
path lu[200100];

int cmp(path a,path b)// 白先
{
    return a.c>b.c;
}

int cmp2(path a,path b)
{
    return a.c<b.c;
}
int main()
{
    int i,t;
    int big,sml;
    tt[1]=1,tt[2]=2;
    for(i=3;;i++)
    {
        tt[i]=tt[i-2]+tt[i-1];
        if(tt[i]>100000)
            break;
    }
    int cas=1;
    int u,v,n,m,flag;
    int x,y;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&lu[i].u,&lu[i].v,&lu[i].c);
        }

        flag=1;
        // 求大的
        for(i=1;i<=n;i++)
            f[i]=i;
        sort(lu,lu+m,cmp);
        big=0;
        for(i=0;i<m;i++)
        {
            x=lu[i].v;
            y=lu[i].u;
            if(find(x)!=find(y))
            {
                Union(x,y);
                big+=lu[i].c;
            }
        } 

        for(i=1;i<=n;i++)//
        {
            if(find(i)!=find(1))
                flag=0;
        }

        sml=0;
        for(i=1;i<=n;i++)
            f[i]=i;
        sort(lu,lu+m,cmp2);
        for(i=0;i<m;i++)
        {
            x=lu[i].v;
            y=lu[i].u;
            if(find(x)!=find(y))
            {
                Union(x,y);
                sml+=lu[i].c;
            }
        } 

        for(i=1;i<=n;i++)//
        {
            if(find(i)!=find(1))
                flag=0;
        }

        printf("Case #%d: ",cas++);
        if(flag==0)
        {
            printf("No\n");
            continue;
        }

    //    printf("%d\n",tt[25]);
        flag=0;
        for(i=1;i<=24;i++)
        {
            if(tt[i]<=big&&tt[i]>=sml)
                flag=1;
        }
        if(flag)
            puts("Yes");
        else
            puts("No");
    }
    return 0;
}
时间: 2024-10-13 16:43:21

HDU 4786 Fibonacci Tree 并查集+生成树=kruskal的相关文章

hdu 4786 Fibonacci Tree (最小、最大生成树)

题意: N个点,M条边.每条边连接两个点u,v,且有一个权值c,c非零即一. 问能否将N个点形成一个生成树,并且这棵树的边权值和是一个fibonacii数. (fibonacii数=1,2,3,5,8 .... ) 思路: 若可以生成一棵树.则有最小生成树和最大生成树.假设已经生成了最小MST  P 和最大MST  Q. 将P更换一条边可以得到另一棵生成树,边权和不是和P相等就是比P的边权和大1.(因为边值非零即一).同理搞下去....一定可以得到Q. 所以P的边权和到Q的边权和之间的所有值都能

HDU 4786 Fibonacci Tree 最小生成树变形

思路: 这题比赛的时候想了好久,最后队友机智的想到了. 不过那时不是我敲的,现在敲的1A. 想好就容易了. 直接把1或者0当做边的权值,然后按边从小到大排序,然后算最小生成用到了几条白边,然后再按边从大到小排序,然后再算白边用了几条.然后最小和最大需要用到的白边都算出来了.如果在这最小最大区间中存在那个啥数列的话就是Yes,否则就是No. 为什么在这区间里面就是对的呢?刚开始我也想了好久,然后发现,因为白边权值是1,然后黑边是0,然后假设用到白边最小的是6,最大的是10,那么,我们可以用黑边去替

HDU 4786 Fibonacci Tree(生成树,YY乱搞)

http://acm.hdu.edu.cn/showproblem.php?pid=4786 Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1733    Accepted Submission(s): 543 Problem Description Coach Pang is interested in

hdu 4786 Fibonacci Tree

题目:大致的意思就是说给定n个点和m条边,这m条边分成两种颜色----白色和黑色,问是否可以形成一个生成树使得白色边的个数是一个斐波那契数. 思路:求出白色边能形成的联通图(非环)的最多边数和最少边数.最大数能够用白边的并查集求得(max=num).而最少边数能够用黑边的并查集求的(min=n-1-num).然后再看在min--max之间是否存在斐波那契数就能够了. 解释:为什么这样求联通图的白边的个数区间是对的呢?首先上限就不用说了.那么我们想如果这个图可以形成生成树,这颗树里面除了白边就是黑

hdu 4786 Fibonacci Tree ( 最小生成树 )

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2487    Accepted Submission(s): 796 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

hdu 4786 Fibonacci Tree(最小生成树)

Fibonacci Tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2952    Accepted Submission(s): 947 Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him t

hdu 3938 Portal(并查集+离线+kruskal)

搜了题解才把题搞明白.明白之后发现其实题意很清晰,解题思路也很清晰,只是题目表述的很不清晰…… 大意如下—— 给你一个无向图,图中任意两点的距离是两点间所有路径上的某一条边,这条边需要满足两个条件:1. 这条边这两点间某条路径上的最长边:2. 这条边是这两点间所有路径上的最长边中的最短边. 简单来说,假如a到d有两条路径,一条经过b,一条经过d,其中ab = 1, bd = 3, ac = 2, cd = 2,那么abd上的最长边为3,acd上的最长边为2,则ad的距离为2. 如果a, d两点间

HDU 4786 Fibonacci Tree 生成树

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4786 题意:有N个节点(1 <= N <= 10^5),M条边(0 <= M <= 10^5).当中一部分边被染成了黑色,剩下的边是白色,问能不能建立一棵树,树中有斐波那契数个白色边. 思路:用克鲁斯卡尔建三次树,第一是用全部边建树.推断能否建成一棵树,第二次用黑边建树,最多能够用到x条黑边(不成环),n-1-x就是最少须要用的白边的数量,第三次用白边建树,最多能够用到y条白边.假设在[y

hdu 4786 Fibonacci Tree (最小生成树扩展)

///白边优先和黑边优先做两次最小生成树 ///若有斐波那契树在这中间为yes # include <stdio.h> # include <algorithm> # include <iostream> # include <string.h> # include <math.h> using namespace std; struct node { int x; int y; int v; }; struct node a[100010];