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

## 题目描述

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

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.

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

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

## 输入输出格式

The first line of input contains N

path in terms of the pair of barns it connects (barns are conveniently numbered

1 \ldots N

describing the order in which the barns will be closed.

The output consists of N

indicates whether the initial farm is fully connected, and line i+1

whether the farm is fully connected after the i

## 输入输出样例

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

YES
NO
YES
YES分析：并查集的经典应用，无向图求联通用并查集，但是一个一个删点不好处理，那么就离线倒着加点，放到并查集里，看最后连通块的个数是不是只有1个，不过有一个坑点，加点后判断连通块个数时一定不能考虑没有加进去的点！程序里用flag数组标明了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

const int maxn = 3010;

int n,m,head[maxn],to[maxn * 2],nextt[maxn * 2],tot = 1,fa[maxn],flag[maxn],a[maxn];
bool ans[maxn];

{
to[tot] = y;
}

int find(int x)
{
if (x == fa[x])
return x;
return fa[x] = find(fa[x]);
}

int main()
{
scanf("%d%d",&n,&m);
for (int i = 1; i <= n; i++)
fa[i] = i;
for (int i = 1; i <= m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
}
for (int i = n; i >= 1; i--)
scanf("%d",&a[i]);
for (int i = 1; i <= n; i++)
{
int cnt = 0;
flag[a[i]] = 1;
for (int j = head[a[i]];j;j = nextt[j])
{
int v = to[j];
if (flag[v])
{
int fx = find(a[i]),fy = find(v);
if (fx != fy)
fa[fx] = fy;
}
}
for (int j = 1; j <= n; j++)
if (flag[j] && fa[j] == j)
cnt++;
if (cnt == 1)
ans[n + 1 - i] = 1;
else
ans[n + 1 - i] = 0;
}
for (int i = 1; i <= n; i++)
{
if (ans[i])
printf("YES\n");
else
printf("NO\n");
}

return 0;
}


posted @ 2017-09-10 09:22 zbtrs 阅读(...) 评论(...) 编辑 收藏