• 洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm_Silver


    洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm_Silver

    题目描述

    FJ和他的奶牛们正在计划离开小镇做一次长的旅行,同时FJ想临时地关掉他的农场以节省一些金钱。

    这个农场一共有被用M条双向道路连接的N个谷仓(1<=N,M<=3000)。为了关闭整个农场,FJ 计划每一次关闭掉一个谷仓。当一个谷仓被关闭了,所有的连接到这个谷仓的道路都会被关闭,而且再也不能够被使用。

    FJ现在正感兴趣于知道在每一个时间(这里的“时间”指在每一次关闭谷仓之后的时间)时他的农场是否是“全连通的”——也就是说从任意的一个开着的谷仓开始,能够到达另外的一个谷仓。注意自从某一个时间之后,可能整个农场都开始不会是“全连通的”。

    输入输出格式

    输入格式:

    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 ldots N$). The final $N$ lines give a permutation of $1 ldots N$

    describing the order in which the barns will be closed.

    输出格式:

    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 $i$th closing.

    输入输出样例

    输入样例#1: 复制
    4 3
    1 2
    2 3
    3 4
    3
    4
    1
    2
    输出样例#1: 复制
    YES
    NO
    YES
    YES

    代码

    题目大意:每次删除一个点询问剩下的点是否连通。
    逆序并查集维护。

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int can[3001],n;
    int fa[3001];
    int ans[3001],a[3001];
    int h[3001],ne[6001],to[6001],fr[6001],en=0;
    inline void add(int a,int b)
    {ne[en]=h[a];to[en]=b;fr[en]=a;h[a]=en++;}
    inline int gf(int k)
    {
        if (fa[k]==k) return k;
        else return fa[k]=gf(fa[k]);
    }
    int main()
    {
        memset(h,-1,sizeof h);
        int n,m;
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        for (int i=1;i<=n;++i) scanf("%d",&a[i]),fa[i]=i;
        for (int i=n;i>=1;--i)
        {
            can[a[i]]=1;
            for (int j=h[a[i]];j>=0;j=ne[j])
            {
                if (can[fr[j]]&&can[to[j]])
                {
                    int l=fr[j],r=to[j];
                    int fl=gf(l),fr=gf(r);
                    if (fl!=fr) fa[fl]=fr;
                }
            }
            int cnt=0;
            for (int j=1;j<=n;++j)
                if (can[j]&&fa[j]==j) cnt++;
            if (cnt==1) ans[i]=1;
        }
        printf("YES
    ");
        for (int i=2;i<=n;++i) if (ans[i]) printf("YES
    ");
        else printf("NO
    ");
    }
  • 相关阅读:
    51nod 1122 机器人走方格 V4(矩阵乘法)
    51nod 1092 回文字符串
    51nod 1254 最大子段和 V2(递推)
    容斥原理求gcd为k的数对个数
    51nod 1115 最大M子段和 V3
    51nod 1053 最大M子段和 V2(贪心)
    洛谷P1792 [国家集训队]种树
    洛谷P1484 种树(反悔贪心,双向链表+堆)
    51 nod 1052 最大M子段和
    51 nod 1051 最大子矩阵和
  • 原文地址:https://www.cnblogs.com/huihao/p/7788550.html
Copyright © 2020-2023  润新知