1346:【例4-7】亲戚(relation)

简介: 1346:【例4-7】亲戚(relation)

1346:【例4-7】亲戚(relation)

时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

或许你并不知道,你的某个朋友是你的亲戚。他可能是你的曾祖父的外公的女婿的外甥女的表姐的孙子。如果能得到完整的家谱,判断两个人是否是亲戚应该是可行的,但如果两个人的最近公共祖先与他们相隔好几代,使得家谱十分庞大,那么检验亲戚关系实非人力所能及。在这种情况下,最好的帮手就是计算机。为了将问题简化,你将得到一些亲戚关系的信息,如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

1. //示例代码  会超时
2. #include <iostream>
3. using namespace std;
4. int f[20005];
5. int find(int x){//查找x所在的集合
6.  if(f[x]==x) return x;//如果x自己就是一个集合的根节点,则返回x
7.  return f[x]=find(f[x]);//否则递归查找x的祖先节点
8. }
9. void unionn(int x,int y){//将x和y所在的集合合并
10.   f[find(x)]=find(y);
11. }
12. int main()
13. {
14.   int n,m,q,a,b;
15.   cin>>n>>m;
16.   for(int i=1;i<=n;i++) f[i]=i;//初始化每个人为一个单独的集合
17.   for(int i=1;i<=m;i++){ //处理已知亲戚关系
18.     cin>>a>>b;unionn(a,b);
19.   }
20.   cin>>q;
21.   for(int i=1;i<=q;i++){//查询每一对可能的亲戚
22.     cin>>a>>b;
23.     if(find(a)==find(b)) cout<<"Yes"<<endl;
24.     else cout<<"No"<<endl;
25.   }
26. return 0;
27. }

以上程序使用了并查集的数据结构。首先将每个人自己作为一个集合,并将已知的亲戚关系两个人所在的集合进行合并。然后对于每个询问,判断两个人是否所在同一个集合即可。在并查集上使用路径压缩优化之后,时间复杂度为O(mlogn)。以上代码会超时。

1. // 示例代码  AC
2. #include <iostream>
3. #include <stdio.h>
4. using namespace std;
5. int f[20005];
6. int find(int x){//查找x所在的集合
7.  if(f[x]==x) return x;//如果x自己就是一个集合的根节点,则返回x
8.  return f[x]=find(f[x]);//否则递归查找x的祖先节点
9. }
10. void unionn(int x,int y){
11.   f[x]=y;
12. }
13. int main()
14. {
15.   int n,m,q,a,b;
16.   scanf("%d %d",&n,&m);
17.   for(int i=1;i<=n;i++) f[i]=i;//初始化每个人为一个单独的集合 
18.   for(int i=1;i<=m;i++){ //处理已知亲戚关系
19.     scanf("%d %d",&a,&b);
20.     int x=find(a);
21.     int y=find(b);
22.     if(x!=y) unionn(x,y);
23.   }
24.   cin>>q;
25.   for(int i=1;i<=q;i++){//查询每一对可能的亲戚
26.     scanf("%d %d",&a,&b);
27.     if(find(a)==find(b)) puts("Yes");
28.     else puts("No");
29.   }
30. return 0;
31. }

这串代码必须用C语言的输入输出才能AC。


相关文章
2022天梯赛三月冲刺——PAT (Advanced Level)1013 Battle Over Cities (并查集找连通块)
2022天梯赛三月冲刺——PAT (Advanced Level)1013 Battle Over Cities (并查集找连通块)
116 0
|
C++ 容器
【PAT甲级 - C++题解】1025 PAT Ranking
【PAT甲级 - C++题解】1025 PAT Ranking
64 0
|
C++ 容器
【PAT甲级 - C++题解】1141 PAT Ranking of Institutions
【PAT甲级 - C++题解】1141 PAT Ranking of Institutions
87 0
LeetCode Contest 178 1366. 通过投票对团队排名 Rank Teams by Votes
LeetCode Contest 178 1366. 通过投票对团队排名 Rank Teams by Votes
2021年度训练联盟热身训练赛第一场——Early Orders(单调栈)
2021年度训练联盟热身训练赛第一场——Early Orders(单调栈)
63 0
2019牛客暑期多校2-Partition problem深搜
题意: 将2*n个人分成两部分,每部分都有n个人 而且每个人只能属于一个组,问按照给出的算式得到的竞争力最大值是多少
97 0
2019牛客暑期多校2-Partition problem深搜