HDU - 4786 Fibonacci Tree (MST)

题意:给一张由白边和黑边构成的无向图,求是否存在一个生成树,使白边的数量为一个斐波那契数。
分析:白边权值为1,黑边权值为0。求出该图的最小生成树和最大生成树,若这两个值之间存在斐波那契数,则可以,若不存在或者所给的图不是连通图,则不行。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
set<int> dp;

struct Edge{
    int u,v,w;
}edge[maxn<<1];
int n,m;

bool cmp (const Edge & x,const Edge & y) {
    return x.w<y.w;
}

bool cmp2(const Edge &x, const Edge &y) {
    return x.w>y.w;
}

int fa[maxn];
void init()
{
    for(int i=0;i<=n;++i) fa[i] = i;
}

int Find(int x)
{
    return fa[x] ==x ? x: fa[x] = Find(fa[x]);
}

void Union(int x,int y)
{
    int fx = Find(x), fy = Find(y);
    fa[fx] = fy;
}

int kruskal()
{
    init();
    int res = 0, cnt = 0;
    for(int i=1,u,v,w;i<=m;++i){
        u =edge[i].u, v= edge[i].v, w =edge[i].w;
        if(Find(u)!=Find(v)){
            Union(u,v);
            res += w;
            ++cnt;
            if(cnt>=n-1) break;
        }
    }
    if(cnt<n-1) return -1;
    return res;
}

int kruskal2()
{
    init();
    int res = 0, cnt= 0;
    for(int i=m,u,v,w;i>=1;--i){
        u =edge[i].u, v= edge[i].v, w =edge[i].w;
        if(Find(u)!=Find(v)){
            Union(u,v);
            res += w;
            ++cnt;
            if(cnt>=n-1) break;
        }
    }
    if(cnt<n-1) return -1;
    return res;
}

int fib[maxn];
int pt;

void pre()
{
    fib[1] = 1, fib[2] = 2;
    dp.insert(1);
    dp.insert(2);
    int i;
    for(i=3;i<maxn;++i){
        fib[i] = fib[i-1] + fib[i-2];
        dp.insert(fib[i]);
        if(fib[i]>100000) break;
    }
}

int main()
{
    int T,cas=1;
    scanf("%d",&T);
    pre();
    while(T--){
        scanf("%d %d",&n, &m);
        for(int i=1;i<=m;++i){
            scanf("%d %d %d",&edge[i].u, &edge[i].v, &edge[i].w);
        }
        sort(edge+1,edge+m+1,cmp);

        int t1 = kruskal();
        int t2 = kruskal2();
        if(t1>t2) swap(t1,t2);
        
        printf("Case #%d: ",cas++);
        bool f = false;
        for(int i=t1;i<=t2;++i){
            if(dp.find(i)!=dp.end()){
                f = true;
                break;
            }
        }
        if(f) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}

posted @ 2018-10-08 10:58  xiuwenL  阅读(156)  评论(0编辑  收藏  举报