zoukankan      html  css  js  c++  java
  • HDU 4786 生成树 并查集+极大极小值 黑白边 确定选择白边的数量

    题意:

    给定一个无向图

    n 个点 m条无向边

    u v val

    val == 1 表示边(u, v) 为白边

    问能否找到n个点的生成树, 使得白边数为斐波那契数

    思路:

    并查集求图是否连通( 是否存在生成树)

    求出 最多白边树 的 白边数量

    求出 最少白边树 的 白边数量

    若[最少, 最多] 区间内存在斐波那契数 ,则满足条件

    (也就是说,白边的数量是连续有解的)

    //YY得证

    #include<iostream>
    #include<stdio.h>
    #include<algorithm>
    #include<string>
    #include<queue>
    #include<string.h>
    #include<map>
    #include<set>
    #include<stack>
    #include<vector>
    #include<math.h>
    #include<algorithm>
    #define N 101010
    #define inf 10000000
    using namespace std;
    inline int Min(int a,int b){return a>b?b:a;}
    inline int Max(int a,int b){return a<b?b:a;}
    
    int f[N];
    int find(int x){return x==f[x]?x:(f[x] = find(f[x]));}
    void Union(int u, int v){
        int fu = find(u), fv = find(v);
        if(fu>fv)
            f[fu] = fv;
        else 
            f[fv] = fu;
    }
    set<int>fib;
    int n, m;
    struct node{
        int u,v,c;
    }edge[N];
    int edgenum;
    bool cmp1(node a,node b){return a.c<b.c;}
    bool cmp2(node a,node b){return a.c>b.c;}
    int main(){
        int T, Cas = 1;scanf("%d",&T);
        int i, j, col;
        fib.clear();
        fib.insert(1);
        fib.insert(2);
        j=1;
        for(i=2;i<=N;){
            fib.insert(i+j);
            int lala = i;
            i = i+j;
            j = lala;
        }
        while(T--){
            scanf("%d %d", &n, &m);
            for(i=1;i<=n;i++)f[i] = i;
            edgenum = 0;
            while(m--){
                int u,v;
                scanf("%d %d %d",&u,&v,&col);
                edge[edgenum].u = u;
                edge[edgenum].v = v;
                edge[edgenum++].c = col;
    
                int fx = find(u), fy = find(v);
                if(fx == fy)continue;
                Union(fx,fy);
    
            }
            printf("Case #%d: ",Cas++);
            for(i=1;i<=n;i++)find(i);
            bool su = true;
            for(i=1;i<=n;i++)
                if(f[i]!=f[1])
                {su = false; break;}
    
                if(su == false)
                {printf("No
    ");continue;}
                for(i=1;i<=n;i++)f[i] = i;
                sort(edge, edge+edgenum, cmp1);
                int size = 0, bl=0, bm=0;
                for(i=0;i<edgenum;i++)
                {
                    int u =edge[i].u, v=edge[i].v;
                    int fu = find(u), fv=find(v);
                    if(fu == fv)continue;
                    size++;
                    bl+= edge[i].c;
                    Union(fu, fv);
                    if(size==n-1)break;
                }
                for(i=1;i<=n;i++)f[i] = i;
                sort(edge, edge+edgenum, cmp2);
                size = 0;
                for(i=0;i<edgenum;i++)
                {
                    int u =edge[i].u, v=edge[i].v;
                    int fu = find(u), fv=find(v);
                    if(fu == fv)continue;
                    size++;
                    bm+= edge[i].c;
                    Union(fu, fv);
                    if(size==n-1)break;
                }
    
                if(fib.upper_bound(bl) == fib.end() ){printf("No
    ");continue;}
                if((*fib.lower_bound(bl) )>bm){printf("No
    ");continue;}
                
    
    
                printf("Yes
    ");
        }
        return 0;
    }
    /*
    4 2
    1 2 1
    3 4 1
    
    */
    


     

  • 相关阅读:
    EIGRP-16-其他和高级的EIGRP特性-2-非等价负载分担
    EIGRP-15-其他和高级的EIGRP特性-1-路由器ID
    EIGRP-14-EIGRP的命名模式
    EIGRP-13-弥散更新算法-停滞在活动状态
    EIGRP-12-弥散更新算法-DUAL的FSM(*没写完)
    EIGRP-11-弥散更新算法-EIGRP中的本地计算和弥散计算
    EIGRP-10-弥散更新算法-计算距离,报告距离,可行距离和可行性条件
    EIGRP-9-弥散更新算法-拓扑表
    EIGRP-8-路由器的邻接关系
    EIGRP-7-可靠传输协议
  • 原文地址:https://www.cnblogs.com/riasky/p/3431089.html
Copyright © 2011-2022 走看看