P3144 [USACO16OPEN]关闭农场Closing the Farm

https://www.luogu.org/problem/show?pid=3144#sub

这里写图片描述
这里写图片描述

分析:按顺序去掉点后查询图是否还是联通的,那么我们就可以按照删除的顺序倒着加点。
在加某个点之前判断图是否是联通的,即按顺序去掉这个点后图是否是联通的。
具体的处理方法:根据输出要求,我们可以先把最后一个去掉的点加进图中;然后在倒着放入其它点
(第i个点)之前先判断当前图是否是联通的,将答案存入ans[i+1]中,当i为0时,只判断图是否是联通的,
然后break掉就可以了。

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
vector <int> to[3009];
int n,m,p[3009],f[3009];
string ans[3009];
bool vis[3009];
vector <int> q;
int find(int x)
{
    return x==f[x]?x:f[x]=find(f[x]);
}
void add(int x)
{
    for(int i=0;i<to[x].size();i++)
     if(vis[to[x][i]]) f[find(x)]=find(to[x][i]);

    q.push_back(x);
    vis[x]=1;
}
bool judge()
{
    if(!q.size()) return true;
    else{
        int fa=find(q[0]);
        for(int i=1;i<q.size();i++)
        {
            int k=q[i];
            if(find(k)!=fa) 
            return false;
        }
    }
    return true;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        to[x].push_back(y);
        to[y].push_back(x);
    }
    for(int i=1;i<=n;i++)
     scanf("%d",&p[i]);
    add(p[n]);
    for(int i=n-1;i>=0;i--)
    {
        if(judge()) ans[i+1]="YES";
        else ans[i+1]="NO";

        if(i==0) break;

        add(p[i]);
    }
    for(int i=1;i<=n;i++)
     cout<<ans[i]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/dfsac/p/7587870.html