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;
}