L2-4 部落(25 分)

xiaoxiao2021-02-28  27

题目链接 在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。 输入格式: 输入在第一行给出一个正整数N(≤10​4),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人: K P[1] P[2] ⋯ P[K] 其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过10​4​​。 之后一行给出一个非负整数Q(≤10​4​​),是查询次数。随后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 注意事项: 1.并查集计算互不相干的部落数时,必须注意人数可能与10​4不一样大 2.必须要先输入一个,然后在和后面的每一位并起来

#include<iostream> #include<set> using namespace std; int f[10001]; int getf(int x){ if(f[x] == x) return f[x]; f[x] = getf(f[x]); return f[x]; } void merge(int x,int y){ int tx = getf(x); int ty = getf(y); if(tx != ty) f[ty] = tx; return; } int main(){ set <int> s; int n,k,a,b,q,cnt,d,e; scanf("%d",&n); for(int i = 1;i <= 10000;i++)//一开始并不知道有多少人,所以得对总人数进行初始化,一开始写成i <= n,n是圈子数,不是人数!!! f[i] = i;//第二回做,将f[i] = i 写成 f[i] == i,这得是有多粗心 while(n--){ scanf("%d%d",&k,&a); s.insert(a); for(int i = 1;i < k;i++){ scanf("%d",&b); merge(a,b); s.insert(b); } } scanf("%d",&q); cnt = 0; for(int i = 1;i <= s.size();i++)//因为编号从1开始连续编号,因此,确定总人数后,直接到s.size()结束就好 f[i] == i ? cnt++ : cnt; printf("%d %d\n",s.size(),cnt); while(q--){ scanf("%d%d",&d,&e); if(getf(d) != getf(e))//如果祖先相同,就说明是一个部落 printf("N\n"); else printf("Y\n"); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-2350178.html

最新回复(0)