家族 题解

家族 题解

家族

题目

若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
规定: x x x y y y是亲戚, y y y z z z是亲戚,那么 x x x z z z也是亲戚。如果 x x x, y y y是亲戚,那么x的亲戚都是 y y y的亲戚, y y y的亲戚也都是 x x x的亲戚。


输入

第一行:三个整数 n n n, m m m, p p p,( n n n<=50000, m m m<=50000, p p p<=50000),分别表示有 n n n个人, m m m个亲戚关系,询问 p p p对亲戚关系。以下 m m m行:每行两个数 M i Mi Mi M j Mj Mj,1<= M i Mi Mi M j Mj Mj<= N N N,表示 A i Ai Ai B i Bi Bi具有亲戚关系。接下来 p p p行:每行两个数 P i Pi Pi P j Pj Pj,询问 P i Pi Pi P j Pj Pj是否具有亲戚关系。


输出

P P P行,每行一个’ Y e s Yes Yes’或’ N o No No’。表示第i个询问的答案为“具有”或“不具有”亲戚关系。


样例

input
6 5 3
41 2
1 5
3 4
5 2
1 3
1 4
2 3
5 6

output
Yes
Yes
No


解题思路

并查集
预处理
找到父节点,路径压缩
如果两个点不在同一集合
合并父节点

查找
查找父节点
如果在同一集合即为亲戚
反之亦然


代码

#include
#include
using namespace std;
int xx,yy,x,y,n,m,p,f[50020];
int cz(int x)  //并查集
{
	 if (f[x]!=x) 
	    return f[x]=cz(f[x]);  //路径压缩
	    else return x;
}
int main()
{
	scanf("%d%d%d",&n,&m,&p);
	for (int i=1;i<=n;i++)
	    f[i]=i;
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		xx=cz(x); 
		yy=cz(y);  //找父节点
		if (xx!=yy) f[xx]=yy;  //合并
	}
    for (int i=1;i<=p;i++)
    {
    	scanf("%d%d",&x,&y); 
    	xx=cz(x);
    	yy=cz(y);  //找父节点
    	if (xx!=yy)
    	   cout<<"No"<<endl;  //不在同一集合,不是亲戚
    	   else cout<<"Yes"<<endl;  //在同一集合,是亲戚
    }
    return 0;
}

你可能感兴趣的:(并查集)