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 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

题意 : 给你一张无向图,其中有的边为白色,有的边为黑色,问你是否有一颗生

成树并且它的白色边是斐波那契数列中的一个数。

思路 :因为边为白色的权值为1,黑色的权值为0。即在原图的基础上分别求一

遍最小生成树和一遍最大生成树。假设求出的最小生成树的总权值为 Min ,最大

生成树的总权值为 Max , 那么我们可知生成树中最小的白边数为 Min ,最大白

边数为 Max。然后我们只要判断这两个值之间是否存在斐波那契数就行了。

上述结论其实是要证明对于所有在Min和Max之间的白边数都可以。

原因 :在最大生成树上去掉Max - Min 条白边,可知最大生成树会变成

Max - Min+1个连通块,并且这些连通块中已经有 Min条白边 ,所以可知这

Max - Min+1个连通块可以通过 Max - Min 条黑边连接起来 。 将这 Max - Min+1

个连通块看做成 Max - Min+1个点,即这些点可以全通过白边或黑边连接起来。

那么可以得出这些点也可以通过n条白边和m条黑边连接起来 (m+n = Max - Min)。

即可行的白边数为 ans = Min+n , 因为 0 <= n <=Max-Min ,所以 Min <= ans <=Max 。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=100010;
const int N=30;

struct edge
{
    int u,v,val;
} a[maxn];
int id[maxn],f[N]= {0,1,2},n,m,T;

bool cmp1(edge p,edge q)
{
    return p.val<q.val;
}

bool cmp2(edge p,edge q)
{
    return p.val>q.val;
}

int Find(int x)
{
    if(x!=id[x]) id[x]=Find(id[x]);
    return id[x];
}

void input()
{
    scanf("%d %d",&n,&m);
    for(int i=0; i<m; i++) scanf("%d %d %d",&a[i].u,&a[i].v,&a[i].val);
}

int kru()
{
    for(int i=0; i<maxn; i++)  id[i]=i;
    int res=0,num=0;
    for(int i=0; i<m; i++)
    {
        int p=Find(a[i].u),q=Find(a[i].v);
        if(p!=q)
        {
            id[p]=q;
            res+=a[i].val;
        }
    }
    for(int i=1; i<=n; i++)  if(Find(i)==i)  num++;
    if(num>1)  return -1;
    return res;
}

void solve(int co)
{
    int l,r;
    sort(a,a+m,cmp1);
    l=kru();
    sort(a,a+m,cmp2);
    r=kru();
    if(l==-1 || r==-1)
    {
        printf("Case #%d: No\n",co);
        return ;
    }
    else
    {
        for(int i=1; i<N; i++)
        {
            if(f[i]>=l && f[i]<=r)
            {
                printf("Case #%d: Yes\n",co);
                return ;
            }
        }
        printf("Case #%d: No\n",co);
    }
}

int main()
{
    for(int i=3; i<N; i++)  f[i]=f[i-1]+f[i-2];
    scanf("%d",&T);
    for(int co=1; co<=T; co++)
    {
        input();
        solve(co);
    }
    return 0;
}
时间: 2024-08-03 04:55:30

hdu 4786 Fibonacci Tree ( 最小生成树 )的相关文章

HDU 4786 Fibonacci Tree 最小生成树变形

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

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];

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(最小生成树)

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 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 t

HDU 4786 Fibonacci Tree (2013成都1006题) 最小生成树+斐波那契

题意:问生成树里能不能有符合菲波那切数的白边数量 思路:白边 黑边各优先排序求最小生成树,并统计白边在两种情况下数目,最后判断这个区间就可以.注意最初不连通就不行. 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include<cmath> 5 #define LL long long 6 using namespace std; 7 int t,n,m; 8 int

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 (最小、最大生成树)

题意: 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

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