第三部分 数据结构 -- 第四章 图论算法-1346:【例4-7】亲戚(relation)

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");
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章