1389:亲戚
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 3858 通过数: 1211
【题目描述】
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的某个人所在家族的人数。
规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
【输入】
第一行:三个整数n,(n≤100,000,m≤200,000),分别表示有n个人,m个信息。
以下m行:信息包含两种形式:
M a b:表示a和b具有亲戚关系。
Q a:要求输出a所在家族的人数。
【输出】
要求输出a所在家族的人数。
【输入样例】
5 10
M 3 2
Q 4
M 1 2
Q 4
M 3 2
Q 1
M 3 1
Q 5
M 4 2
Q 4
【输出样例】
1
1
3
1
4
思路:求a所在家族人数,我们将家族看成集合,如果两人是亲戚,就合并他们所在集合,询问即所求集合内元素的数量,用并查集解决该问题。增加一个数组记录集合内元素数量,用于求答案。
#include<cstdio>
#include<iostream>
#include<cstring>
#define N 100001
using namespace std;
int father[N];
int cnt[N];
int find(int x){//查找根节点
if(father[x] == x)
return x;
return father[x] = find(father[x]);
}
void un(int x, int y){
x = find(x);
y = find(y);
if(x != y){
father[y] = x;
cnt[x] += cnt[y];
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++)
{
father[i] = i;//初始化集合
cnt[i] = 1;
}
while(m--){
char ch[10];
scanf("%s",ch);
if(ch[0] == 'M')
{
int a,b;
scanf("%d%d",&a,&b);
un(a,b);
}
if(ch[0] == 'Q')
{
int a;
scanf("%d",&a);
printf("%d\n",cnt[find(a)]);
}
}
return 0;
}