zoukankan      html  css  js  c++  java
  • 续并查集学习笔记——Closing the farm题解

    在很多时候,并查集并不是一个完整的解题方法,而是一种思路。

    通过以下题目来体会并查集逆向运用的思想。

    Description

    Farmer John and his cows are planning to leave town for a long vacation, and so FJ wants to temporarily close down his farm to save money in the meantime.The farm consists of NN barns connected with MM bidirectional paths between some pairs of barns (1≤N,M≤200,000). To shut the farm down, FJ plans to close one barn at a time. When a barn closes, all paths adjacent to that barn also close, and can no longer be used.FJ is interested in knowing at each point in time (initially, and after each closing) whether his farm is "fully connected" -- meaning that it is possible to travel from any open barn to any other open barn along an appropriate series of paths. Since FJ's farm is initially in somewhat in a state of disrepair, it may not even start out fully connected.

    Input

    The first line of input contains N and M. The next M lines each describe a path in terms of the pair

     of barns it connects (barns are conveniently numbered 1…N). The final N lines give a permutation o

    f 1…N describing the order in which the barns will be closed.

    Output

    The output consists of N lines, each containing "YES" or "NO". The first line indicates whether the initial farm is fully connected, and line i+1 indicates whether the farm is fully connected after the iith closing.

    Sample Input

    4 3

    1 2

    2 3

    3 4

    3

    4

    1

    2

    Sample Output

    YES

    NO

    YES

    YES

    显然,按照正向逻辑,每次删去一条边都必须检查整幅图的连通性,做法过于冗杂,时间复杂度高。换一种思维,我们将一个一个点加进图中,通过并查集来维护图的连通性,则可以再Om的时间之内完成。程序如下。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    struct line{
        int to;
        int next;
    }; line a[500020];
    int head[500020];
    int n,m,be[500020],ans[500020],fa[500020],que[500020];
    int getf(int k){                         //并查集常规+路径压缩
        if(fa[k]!=k)fa[k]=getf(fa[k]);
        return fa[k];
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=m;++i){
            int x,y;
            scanf("%d%d",&x,&y);
            a[2*i-1].next=head[x];         //每条边看做两条单向边处理,运用链式前向星保证空间充足
            a[2*i-1].to=y;
            head[x]=2*i-1;
            a[2*i].next=head[y];
            a[2*i].to=x;
            head[y]=2*i;
        }
        for(int i=n;i>=1;--i)scanf("%d",&que[i]);
        
        for(int i=1;i<=n;++i)fa[i]=i;
        
        int num=1;
        be[que[1]]=1;
        ans[1]=1;
    
        for(int i=2;i<=n;++i){
            num++;                          //加入一个新的点,num记录当前图中的集合个数,只有一个集合时说明图连通
            be[que[i]]=1;                   //bei表示这个点已经加入图中
            int now=head[que[i]];
            while(now!=0){
                if(be[a[now].to]==1){
                    int fx=getf(a[now].to);
                    if(fx!=que[i]){
                        num--;
                        fa[fx]=que[i];
                    }
                }
                now=a[now].next;
            }
            if(num==1)ans[i]=1;
            else ans[i]=2;
        }
        
        for(int i=n;i>=1;--i){              //逆向输出
            if(ans[i]==1)printf("YES
    ");
            else printf("NO
    ");
        }
        return 0;
    }

    To be continue......

  • 相关阅读:
    Ceres求解直接法BA实现自动求导
    栈溢出漏洞原理详解与利用
    【机器学习】使用CNN神经网络实现对图片分类识别及模型转换
    【Android】java中调用JS的方法
    5 项大奖,70 项满分!阿里云全方位引领云原生技术升级
    分布式系统架构与云原生—阿里云《云原生架构白皮书》导读
    Dubbo-go 发布 1.5 版,朝云原生迈出关键一步
    阿里产品专家:高情商的技术人,如何做沟通?
    CNCF 新增两个孵化项目 | 云原生生态周报 Vol. 58
    掌门教育微服务体系 Solar | 阿里巴巴 Nacos 企业级落地上篇
  • 原文地址:https://www.cnblogs.com/cxl681237/p/6140358.html
Copyright © 2011-2022 走看看