文章目录
- 题目解读
- 输入格式
- 输出格式
- 思路
- Ac Code
- 参考
题目解读
我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
输入格式
第一行给出一个正整数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主,一天能吃五顿饭
🌻编写本篇文章目的是笔者想以输出的形式进行学习,顺便记录学习点滴🌻
🌹 如果本篇文章对你有帮助的话那就点个赞吧👍🌹
😇 本篇文章可能存在多处不足,如有修改意见,可以私信或者评论我哦 😇