• HDU


    题意:给一张由白边和黑边构成的无向图,求是否存在一个生成树,使白边的数量为一个斐波那契数。
    分析:白边权值为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
    ");
            else printf("No
    ");
        }
        return 0;
    }
    
    
  • 相关阅读:
    NOI模拟赛 6.20
    NOI模拟赛 6.17
    NOI模拟赛 6.16
    计算几何学习笔记
    NOI(p)模拟赛 5.30
    NOI模拟赛 5.26
    [AGC022E] Median Replace 题解
    看完魔圆之后的一点感想(大概
    OI学习日志 11月份
    2021 CSP-S 游记
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9753128.html
Copyright © 2020-2023  润新知