L2-024 部落 #GPLT,并查集 C++


题目解读

我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。

输入格式

第一行给出一个正整数N(≤104),是已知小圈子的个数。
随后N行,每行按一下格式给出一个小圈子里的人:
K P[1] P[2] ⋯ P[K] 其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过104
之后一行给出一个非负整数Q,随后Q行,每行给出一对儿被查询的人的编号

输出格式

首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y,否则输出N。

思路

使用并查集,将每个圈子的第一个人作为父节点,在合并集合的过程当中,统计人的个数,最后根节点的个数就是圈子的个数,而查询是否属于同一个圈子是并查集的基本应用

Ac Code

#include<bits/stdc++.h>

using namespace std;

//最多这么多人 
const int N = 1e4+10;
int f[N];
 
//先写并查集板子
int find(int u){
	if(f[u]!=u)f[u]=find(f[u]);
	return f[u];
} 

void merge(int a,int b){
	int aa=find(a),bb =find(b);
	
	if(aa!=bb)f[aa]=bb;
}

bool judge(int a,int b){
	return find(a)==find(b);
}
 
int main(){
	int n;
	cin >> n;
	
	map<int,bool> mp;//存储状态 
	
	for(int i=0; i<N; i++)f[i]=i;
	
	for(int i=0; i<n; i++){
		int k;
		cin >> k;
		int fa;
		for(int j=0; j<k; j++){
			if(j==0){
				cin>>fa;
				if(mp.count(fa)==0)mp[fa]=1;
			}else{
				int x;
				cin >> x;
				if(mp.count(x)==0)mp[x]=1;
				merge(x,fa);
			}
		} 
	}
	
	cout<<mp.size()<<" ";
	int res=0;
	for(int i=0; i<N; i++){
		//这个人需要先存在 
		if(mp.count(i) != 0 && f[i]==i)res++;
	} 
	cout<<res<<endl;
	
	int q;
	cin >> q;
	while(q--){
		int a,b;
		cin >> a >> b;
		
		if(judge(a,b))cout<<"Y";
		else cout<<"N";
		cout << endl;
	} 
	
	return 0;
}

参考

B站up主,一天能吃五顿饭


🌻编写本篇文章目的是笔者想以输出的形式进行学习,顺便记录学习点滴🌻

🌹 如果本篇文章对你有帮助的话那就点个赞吧👍🌹

😇 本篇文章可能存在多处不足,如有修改意见,可以私信或者评论我哦 😇


在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值