1346:【例4-7】親戚(relation)
時間限制: 1000 ms 內存限制: 65536 KB
提交數: 14138 通過數: 2701
【題目描述】
或許你並不知道,你的某個朋友是你的親戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孫子。如果能得到完整的家譜,判斷兩個人是否是親戚應該是可行的,但如果兩個人的最近公共祖先與他們相隔好幾代,使得家譜十分龐大,那麼檢驗親戚關係實非人力所能及。在這種情況下,最好的幫手就是計算機。爲了將問題簡化,你將得到一些親戚關係的信息,如Marry和Tom是親戚,Tom和Ben是親戚,等等。從這些信息中,你可以推出Marry和Ben是親戚。請寫一個程序,對於我們的關於親戚關係的提問,以最快的速度給出答案。
【輸入】
輸入由兩部分組成。
第一部分以N,M開始。N爲問題涉及的人的個數(1≤N≤20000)。這些人的編號爲1,2,3,…, N。下面有M行(1≤M≤1000000),每行有兩個數ai,bi,表示已知ai和bi是親戚。
第二部分以Q開始。以下Q行有Q個詢問(1≤ Q ≤1000000),每行爲ci,di,表示詢問ci和di是否爲親戚。
【輸出】
對於每個詢問ci,di,輸出一行:若ci和di爲親戚,則輸出“Yes”,否則輸出“No”。
【輸入樣例】
10 7
2 4
5 7
1 3
8 9
1 2
5 6
2 3
3
3 4
7 10
8 9
【輸出樣例】
Yes
No
Yes
思路:這是一道並查集的題目,我們首先將所有人的父節點設爲自己,如果一對父子的父節點不相同則調用並集函數,在查找時,如果兩者父節點相同證明他們兩是親戚,否則不是。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
int father[20005];
inline void scanf_(int &num)
{
char in=getchar(); num=0;
while(in>'9'||in<'0')in=getchar();
while(in>='0'&&in<='9'){num*=10;num+=in-'0';in=getchar();}
}
int find_father(int x){
int temp=x,a;
while(father[x]!=x)
x=father[x];
while(father[temp]!=temp){
a=temp;
temp=father[temp];
father[temp]=x;
}
return x;
}
void union_(int x,int y){
int xx=find_father(x);
int yy=find_father(y);
if(xx!=yy)
father[xx]=yy;
}
int main(){
int re,n,a,b;
scanf_(re);scanf_(n);
for(int i=1;i<=re;i++)father[i]=i;
for(int i=1;i<=n;i++)
{
scanf_(a);scanf_(b);
union_(a,b);
}
int q;
scanf_(q);
while(q--){
scanf_(a);scanf_(b);
if(find_father(a)==find_father(b))printf("Yes\n");
else printf("No\n");
}
}