专栏文章

题解:AT_abc401_e [ABC401E] Reachable Set

AT_abc401_e题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miphh554
此快照首次捕获于
2025/12/03 12:04
3 个月前
此快照最后确认于
2025/12/03 12:04
3 个月前
查看原文

思路

我们发现想要从顶点 11 出发,通过边能够到达的顶点集合恰好为 {1,2,,k}\{1,2,\ldots,k\} 必须满足集合中的点是连通的,所以用并查集维护,并记录每一个并查集里有多少个数,如果节点 11 所在的并查集里的数少于 ii 个,就输出 1-1,否则就看 11 所在的并查集里数连向多少个不在集合里的点。

代码

CPP
#include <bits/stdc++.h>
using namespace std;
int n,m,b[200010],d[200010],e[200010];
vector<int>a[200001];
set<int>c;
int cz(int x){
	if(b[x]==x){
		return x;
	}
	return b[x]=cz(b[x]);
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		a[x].push_back(y);
		a[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		b[i]=i,d[i]=1;
	}
	for(auto i:a[1]){
		e[i]=1;
		c.insert(i);
	}
	printf("%d\n",c.size());
	for(int i=2;i<=n;i++){
		for(auto j:a[i]){
			if(j<=i){
				int x=cz(i),y=cz(j);
				if(x!=y){
					b[x]=y;
					d[y]+=d[x];
				}
			}
			else{
				if(e[j]==0){
					e[j]=1;
					c.insert(j);
				}
			}
		}
		c.erase(i);
		if(d[cz(i)]==i){
			printf("%d\n",c.size());
		}
		else{
			printf("-1\n");
		}
	}
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...