在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
输入在第一行给出一个正整数N(≤104),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人:
K P[1] P[2] ⋯ P[K]
其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过104。
之后一行给出一个非负整数Q(≤104),是查询次数。随后Q行,每行给出一对被查询的人的编号。
首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y
,否则输出N
。
- 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
#include
using namespace std;
int a[10005];
int find(int x){
if(a[x]!=x)a[x]=find(a[x]);
return a[x];
}//并查集模板
int main(){
int n,q,k,x,y,t=0,z=0,b,c,d;
stack
cin>>n;
while(n--){
cin>>k;
if(k--){cin>>b;if(a[b]==0){a[b]=b;t++;s.push(a[b]);}}//这里可以理解为把第一个人作为首领
while(k--){cin>>c;if(a[c]==0){a[c]=c;t++;s.push(a[c]);}
a[find(b)]=find(c);}//将其余人利用并查集连接,他们属于一个首领,即同一个部落
}
while(s.size()){
d=s.top();
if(a[d]==d)z++;//逐个取出,进行判断,与其说找互不相交的部落的个数,倒不如理解为找部落首领
s.pop();
}
cout<
while(q--){
cin>>x>>y;
if(find(x)==find(y))cout<<"Y\n";
else cout<<"N\n";
}
return 0;
}