码迷,mamicode.com
首页 > 其他好文 > 详细

HDU4786 Fibonacci Tree【最小生成树】

时间:2015-04-24 21:11:45      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4786

 

题目大意:

给你图的N个点和M条双向边。告诉你每条边的权值。权值为1表示该边是白边,权值为0表示该

边为黑边。问:能否找到一棵生成树,使生成树白边的个数恰好为fibonacci数。如果能构成这样

的fibonacci树,输出Yes,否则输出No。

 

思路:

先将fibonacci数列打表。然后根据题意构图。然后根据边的权值大小排序,用Kruskal先求一遍

小生成树,再求一遍最大生成树。如果最小生成树和最大生成树之间存在fibonacci树,则说明

能够成fibonacci树。这是因为如果最大生成树不是fibonacci树,则可以将最大生成树的部分白

边替换成黑边(权值减少),从而去凑成fibonacci树。同理,最小生成树也可以通过将部分黑边替

换成白边从而凑成fibonacci树。如果最小生成树和最大生成树之间找不到fibonacci值,说明构成

不了fibonacci树。

 

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;

struct EdgeNode
{
    int u;
    int v;
    int w;
}Edges[200100];

int cmp(EdgeNode a, EdgeNode b)
{
    return a.w < b.w;
}
int Father[100100],Fibo[100100],j,id,N,M;

int Fibonaci()
{
    Fibo[1] = 1;
    Fibo[2] = 2;
    for(int i = 3; Fibo[i] <= 100100; ++i)
    {
        Fibo[i] = Fibo[i-1] + Fibo[i-2];
        if(Fibo[i] >= 100100)
            return i;
    }
}

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

int Kruskal1()
{
    for(int i = 0; i <= N; ++i)
        Father[i] = i;
    int Num = 0,Sum = 0;
    for(int i = 0; i < id; ++i)
    {
        int u = Find(Edges[i].u);
        int v = Find(Edges[i].v);
        if(u != v)
        {
            Father[u] = v;
            Num++;
            Sum += Edges[i].w;
        }
        if(Num == N-1)
            break;
    }
    if(Num == N-1)
        return Sum;
    else
        return 0;
}

int Kruskal2()
{
    for(int i = 0; i <= N; ++i)
        Father[i] = i;
    int Num = 0,Sum = 0;
    for(int i = id-1; i >= 0; --i)
    {
        int u = Find(Edges[i].u);
        int v = Find(Edges[i].v);
        if(u != v)
        {
            Father[u] = v;
            Num++;
            Sum += Edges[i].w;
        }
        if(Num == N-1)
            break;
    }
    if(Num == N-1)
        return Sum;
    else
        return 0;
}
int main()
{
    int T,kase = 0,u,v,w;
    j = Fibonaci();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        id = 0;
        for(int i = 0; i <= N; ++i)
            Father[i] = i;
        for(int i = 0; i < M; ++i)
        {
            scanf("%d%d%d",&u,&v,&w);
            Edges[id].u = u;
            Edges[id].v = v;
            Edges[id++].w = w;
            Edges[id].u = v;
            Edges[id].v = u;
            Edges[id++].w = w;
        }
        sort(Edges, Edges+id, cmp);
        int Num1 = Kruskal1();
        int Num2 = Kruskal2();
        bool flag = 0;
        for(int i = Num1; i <= Num2; ++i)
        {
            if(flag)
                break;
            for(int k = 1; k < j; ++k)
            {
                if(i == Fibo[k])
                {
                    flag = 1;
                    break;
                }
            }
        }
        if(flag)
            printf("Case #%d: Yes\n",++kase);
        else
            printf("Case #%d: No\n",++kase);
    }

    return 0;
}


 

HDU4786 Fibonacci Tree【最小生成树】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/45251039

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!