首页 > 代码库 > hdu4786 Fibonacci Tree (最小生成树)

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,权值就不是任意可取的了,这个要具体计算的(排列组合,这里先不考虑)。

   剩下的看代码很容易懂。

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
const int maxn=1e5+5;
const int INF=0x3f3f3f3f;

struct Node
{
    int u,v,w;
} node[maxn*2];

int n,m;
int p[maxn];
int F[30];

int cmp1(Node x,Node y)
{
    return x.w<y.w;
}

int cmp2(Node x,Node y)
{
    return x.w>y.w;
}

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

void Union(int x,int y)
{
    x=Find(x);
    y=Find(y);
    p[y]=x;
}

int kruskal()
{
    int q=0,ans=0;
    for(int i=1; i<=m; i++)
    {
        if(Find(node[i].u) != Find(node[i].v))
        {
            ans+=node[i].w;
            Union(node[i].u,node[i].v);
            q++;
        }
        if(q==n-1) break;
    }
    return ans;
}

int main()
{
    F[1]=1,F[2]=2;
    int t;
    for(t=3; F[t]<maxn; t++)
        F[t]=F[t-1]+F[t-2];
    int T;
    scanf("%d",&T);
    for(int tt=1; tt<=T; tt++)
    {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=m; i++)
            scanf("%d%d%d",& node[i].u,& node[i].v,&node[i].w);
        int minn,maxx;

        for(int i=1; i<=n; i++) p[i]=i;
        sort(node+1,node+1+m,cmp1);
        minn=kruskal();

        for(int i=1; i<=n; i++) p[i]=i;
        sort(node+1,node+1+m,cmp2);
        maxx=kruskal();

        int flag=0;
        for(int i=1; i<t; i++)
            if(F[i]>=minn && F[i]<=maxx)
            {
                flag=1;
                break;
            }
        int fa=Find(1);
        for(int i=1; i<=n; i++)
            if(Find(i)!=fa)
            {
                flag=0;
                break;
            }
        if(flag==1) printf("Case #%d: Yes\n",tt);
        else printf("Case #%d: No\n",tt);
    }
    return 0;
}

 

hdu4786 Fibonacci Tree (最小生成树)