L2-024 部落 (并查集与set容器的应用)

题目: 在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
在这里插入图片描述
输入样例:

4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7

输出样例:

10 2
Y
N

题目分析:应用并查集。因为题目要求输出社区总人数以及有几个部落(也就是有几个根节点),可以应用set容器解。
关于并查集和set集合的知识点理解 : 传送门
嗯…对于我这个小白这道题正好练习并查集和set容器了…首先这个输入不是n个朋友圈嘛,然后每行输入第 i 个朋友圈里的人的编号。那就把第一个人当成根节点,然后之后的人直接Join进去,这个Join函数,最后谁做根节点不要紧,形成一个部落才是目标。之后放个迭代器,把根节点的所在编号放到另一个set容器里,set容器相当于一个集合,会自动删去重复项,之后对其进行s.size()就可以得到有多少个部落了。

#include<iostream>
#include<set>
using namespace std;
int pre[10005];//存放根节点 
int init(){ //初始化pre数组 
	for(int i=0;i<10005;i++){
		pre[i]=i;
	}
}

int Find(int x){ //找根节点 
	int r=x;
	while(r!=pre[r]){
		r=pre[r];
	}
	int i=x,j;
	while(pre[i]!=r)//路径压缩 
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}

int Join(int x,int y){	//朋友圈扩大~ 
	int fx=Find(x);
	int fy=Find(y);
	if(fy!=fx){
		pre[fy]=fx;
	}
}

int main(){
	init();
	set<int> s;
	set<int> cs;	//创建俩容器 
	int n,k;
	int p;
	int m,d;
	cin>>n;
	for(int i=0;i!=n;i++){
		cin>>k;
		cin>>m;//把该朋友圈的第一个人的编号树当做头结点
		s.insert(m);
		for(int j=1;j!=k;j++){
			cin>>d;
			s.insert(d);
			Join(m,d);
		} 
	}
	set<int>::iterator iter;	//创建迭代器 
	for(iter=s.begin();iter!=s.end();++iter){
		cs.insert(Find(*iter));
	}
	cout<<s.size()<<" "<<cs.size()<<endl;

	int q;
	cin>>q;
	while(q--){
		int m,n;
		cin>>m>>n;
		if(Find(m)!=Find(n)) cout<<"N"<<endl;
		else cout<<"Y"<<endl;
	}	 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值