1. 程式人生 > >題解之洛谷P1551——並查集的板子題(第一次發部落格如有不好請多多諒解)

題解之洛谷P1551——並查集的板子題(第一次發部落格如有不好請多多諒解)

【題目背景】

若某個家族人員過於龐大,要判斷兩個是否是親戚,確實還很不容易,現在給出某個親戚關係圖,求任意給出的兩個人是否具有親戚關係。

【題目描述】

規定: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個詢問的答案為“具有”或“不具有”親戚關係。

輸入輸出樣例】

【輸入樣例

6 5 3
1 2
1 5
3 4
5 2
1 3
1 4
2 3

5 6

【輸出樣例】

Yes
Yes

No

【說明】

非常簡單的並查集入門題哦!!!

【解題思路】

看到這個題的時候想起的基本演算法有:Floyd求連通性、搜尋、並查集

再瞄一眼資料範圍,Floyd肯定是GG了,搜尋O(N^2)有點勉強的感覺,並查集加了路徑壓縮後接近線性,好了就他了

吐槽下,感覺資料範圍有點小了,1e6的資料感覺正好,甚至可以設定成1e7

廢話不多說下面沾AC程式碼:

/*
	copy by Apojacsleam
*/
#include<cstdio>
#include<cctype>
#define N 5001
int readin();
int n,m,p,fa[N];
int find(int x)
{
	if(fa[x]==x) return x;
	return fa[x]=find(fa[x]);
}
int main()
{
	n=readin();m=readin();p=readin();
	for(register int i=1;i<=n;i++) fa[i]=i;
	int a,b;
	for(register int i=1;i<=m;i++)
	{
		a=readin();b=readin();
		int r1=find(a),r2=find(b);
		if(r1!=r2) fa[r2]=r1;
	}
	for(register int i=1;i<=p;i++)
	{
		a=readin();b=readin();
		int r1=find(a),r2=find(b);
		if(r1==r2) puts("Yes");
		else puts("No");
	}
	return 0;
}
int readin()
{
	int fz=0;char ch=getchar();bool XX=true;
	for(;!isdigit(ch);ch=getchar())
	  if(ch=='-') XX=false;
	for(;isdigit(ch);ch=getchar()) fz=(fz<<3)+(fz<<1)+ch-48;
	return XX?fz:(~fz)+1;
}