并查集--假期关楼



假期关楼
时间限制 : - MS   空间限制 : 65536 KB  
评测说明 : 因文件输入输出过大,时限2000ms
问题描述


暑假到了,大部分学生都回家了,只有少量竞赛学生还在学校里。
学校打算逐步把教学楼都关闭。以减少运营成本。
学校里的N栋教学楼(编号1到N)通过M条双向道路连接起来。每关闭了一栋楼,与该楼相连的所有道路同时都会被关闭。
何老板想知道,学校每关闭一栋楼,剩下的处于开放状态的教学楼是否是连通的。连通就是指任何两个开放的楼都可以相互到达。
注意,有可能一开始所有楼都不连通。


输入格式


第一行,一个两个整数N和M
接下来M行,每行两个整数x和y,表示x、y两栋楼间有道路直接相连。
接下来N行,每行一个整数代表一栋楼的编号。整个N行数字表示依次关闭的教学楼的顺序。


输出格式


共N行,每行是"YES"或者"NO",若剩下的楼是连通的输出YES,否则输出NO。
其中第1行表示一开始整个学校的楼是否连通。
其中第i+1行表示第i次关闭教学楼后,剩下的楼是否连通。


样例输入


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


样例输出


YES
NO
YES
YES


提示


对于40%的数据1≤N,M≤3000   


对于100%的数据1≤N,M≤200000


分析: 因为并查集并没有删除操作,那么就考虑添加而不是删除

关闭楼==倒序打开楼

只需看每次添加后连通块是否只有一个

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
inline void _read(int &x){ 
    char t=getchar();bool sign=true; 
    while(t<'0'||t>'9') 
    {if(t=='-')sign=false;t=getchar();} 
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0'; 
    if(!sign)x=-x; 
}
struct line{
	int from,to;
};
line edge[1000005];
int last[200005],_next[1000005];
int m=0,cnt=0;
int n,num;
int a[200005];
int father[200005];
int ans[200005];
bool open[200005];
void add_edge(int x,int y){
	m++;
	_next[m]=last[x];
	last[x]=m;
	edge[m].from=x;
	edge[m].to=y;
}
int getfather(int x){
	if(x!=father[x])father[x]=getfather(father[x]);
	else return father[x];
}
int main(){
	int i,j,k;
	cin>>n>>num;
	for(i=1;i<=num;i++){
		int x,y;
		_read(x);_read(y);
		add_edge(x,y);
		add_edge(y,x);
	}
	for(i=1;i<=n;i++)father[i]=i;
	for(i=n;i>=1;i--)
		_read(a[i]);
	for(i=1;i<=n;i++){
		int x=a[i];
		cnt++;
		open[x]=true;
		for(int h=last[x];h;h=_next[h]){
			int v=edge[h].to;
			if(open[v]){
				int fx=getfather(x);
				int fy=getfather(v);
				if(fx!=fy){
					father[fx]=fy;
					cnt--;
				}
			}
		}
		ans[i]=cnt;
	}
	for(i=n;i>=1;i--){
		if(ans[i]==1)printf("YES\n");
		else printf("NO\n");
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值