题目背景
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
题目描述
规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。
输入输出格式
输入格式:
第一行:三个整数n,m,p,(n<=5000,m<=5000,p<=5000),分别表示有n个人,m个亲戚关系,询问p对亲戚关系。
以下m行:每行两个数Mi,Mj,1<=Mi,Mj<=N,表示Mi和Mj具有亲戚关系。
接下来p行:每行两个数Pi,Pj,询问Pi和Pj是否具有亲戚关系。
输出格式:
P行,每行一个’Yes’或’No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系。
输入输出样例
输入样例#1:
6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6
输出样例#1:
Yes
Yes
No
今天get新技能并查集,这题比较简单,就是一个简单的裸并查集,直接上代码了;
#include<iostream>
#define maxsize 5000
using namespace std;
int a[maxsize][maxsize];
int b[maxsize][maxsize];
typedef struct node
{
int data;
int rank;
int parent;
}UFSTREE;
void def(UFSTREE ufs[],int n){
for(int i=1;i<=n;i++){//初始化
ufs[i].data=i;
ufs[i].rank=0;
ufs[i].parent=i;//将每个节点自己作为自己的根节点
}
}
int find_x(UFSTREE ufs[],int x){
if(x!=ufs[x].parent)
return find_x(ufs,ufs[x].parent);//递归寻找根节点
else
return x;
}
void union_s(UFSTREE ufs[],int x,int y){
int a=find_x(ufs,x);//找x的根节点
int b=find_x(ufs,y);//找y的根节点
if(ufs[a].rank>ufs[b].rank){//确定深度高的树作为合并后的根节点
ufs[b].parent=a;
}else{
ufs[a].parent=b;
if(ufs[a].rank==ufs[b].rank){//如果深度相同,合并后,深度需要+1
ufs[b].rank++;
}
}
}
int main()
{
UFSTREE ufs[maxsize];
int n,m,p;
cin>>n>>m>>p;
for(int i=0;i<m;i++){//二维数组存储关系
cin>>a[i][0]>>a[i][1];
}
for(int i=0;i<p;i++){//二维数组存储需要检验的关系
cin>>b[i][0]>>b[i][1];
}
def(ufs,n);//初始化
for(int i=0;i<m;i++){
union_s(ufs,a[i][0],a[i][1]);//合并关系
}
for(int i=0;i<p;i++){
if(find_x(ufs,b[i][0])==find_x(ufs,b[i][1]))//确认关系
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}