• USACO Closing the Farm


    USACO Closing the Farm

    洛谷银

    洛谷金

    JDOJ银

    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 N barns connected with M bidirectional paths between some pairs of barns (1≤N,M≤3000). 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 of 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 ith closing.

    Sample Input

    4 3 1 2 2 3 3 4 3 4 1 2

    Sample Output

    YES NO YES YES


    题解:

    分析题意可知,这是一道维护连通性的题。考虑可达性统计,发现过不去大数据。于是考虑并查集。

    并查集需要倒着枚举,因为并查集不能维护删除关系,只能维护合并关系。而且,其实题意也暗示了我们倒叙枚举,因为第(i)行要输出第(i-1)个关闭谷仓后的可达性关系。

    需要注意的是,这里的可达性并非是两两可达,也就是说不一定是一张连通图或者一棵树,多个连通图也是可以的。只有一种情况不合法:单点。

    我们这里用并查集合并边,并且通过维护一个删除优先度来按优先度合并。那么如何判断答案合不合法呢?维护变量K表示当前集合个数,如果K正好等于i,注意i是倒叙枚举的,那么就是合法的,否则就是有单点,不合法。

    那么就是这样的代码:

    #include<cstdio>
    #include<algorithm>
    #define a(i,a,b) for(int i=a;i<=b;i++)
    #define b(i,a,b) for(int i=a;i>=b;i--)
    using namespace std;
    struct node
    {
        int from,to,num;
    };
    const int N=200050;
    node a[N];
    int f[N],h[N],t[N],s[N];
    bool ans[N];
    int p=0,q;
    int n,m;
    int k;
    int find(int x)
    {
        if(f[x]==x) return x;
        return f[x]=find(f[x]);
    }
    void unite(int x,int y)
    {
        x=find(x),y=find(y);
        if(x==y) return;
        k--;
        if(h[x]<h[y])
        f[x]=y;
        else if(h[x]>h[y])
        f[y]=x;
        else
        f[y]=x,h[x]++;
        return;
    }
    bool same(int x,int y)
    {
        if(find(x)==find(y)) return true;
        return false;
    }
    bool cmp(node x,node y)
    {
        return x.num<y.num;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        k=n;
        a(i,0,m-1)
            scanf("%d%d",&a[i].from,&a[i].to);
        a(i,1,n)
        {
            int x;
            scanf("%d",&x);
            t[x]=i;
            s[i]=x;
        }
        a(i,1,n)
            f[i]=i,h[i]=1;
        a(i,0,m-1)
            a[i].num=min(t[a[i].from],t[a[i].to]);
        sort(a,a+m,cmp);
        q=m-1;
        b(i,n,1)
        {
            while(a[q].num>=i)
            {
                unite(a[q].from,a[q].to);
                q--;
            }
            if(k==i) 
                ans[p]=1;
            else 
                ans[p]=0;
            p++;
        }
        b(i,p-1,0)
        {
            if(ans[i])
                printf("YES
    ");
            else
                printf("NO
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Unity 移动端的复制这么写
    Unity如何管理住Android 6.0 调皮的权限
    谷歌商店Apk下载器
    Unity编辑器下重启
    git pull error
    如何简单的实现新手引导之UGUI篇
    linux系统安装python3.5
    Grafana设置mysql为数据源
    hyper -v 虚拟机(win_server)忘记密码重置
    zabbix报错:the information displayed may not be current
  • 原文地址:https://www.cnblogs.com/fusiwei/p/13711913.html
Copyright © 2020-2023  润新知