题目描述
如题,现在有一个并查集,你需要完成合并和查询操作。
输入格式
第一行包含两个整数N,M ,表示共有 N 个元素和 M 个操作。
接下来 M 行,每行包含三个整数 Zi,Xi,Yi 。
当 Zi=1 时,将 Xi 与 Yi 所在的集合合并。
当 Zi=2 时,输出 Xi 与 Yi 是否在同一集合内,是的输出 Y
;否则输出 N
。
输出格式
对于每一个 Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y
或者 N
。
输入输出样例
输入 #1
4 7 2 1 2 1 1 2 2 1 2 1 3 4 2 1 4 1 2 3 2 1 4
输出 #1
N Y N Y
说明/提示
对于 30% 的数据,N≤10,M≤20。
对于 70% 的数据,N≤100,M≤1000。
对于 100% 的数据,1≤N≤10000,1≤M≤2×100000,1≤Xi,Yi≤N,Zi∈{1,2}。
题解
并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。
这一道题是一道并查集,其实就是用一个数组让每一个数指向他的大哥,话不多说,上代码。
#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <cstdio>
#include <cmath>
using namespace std;
int n,m,p,x,y;
int f[5002];
int find(int x){//找大哥
if(x==f[x]){
return x;
}
return find(f[x]);
}
void join(int c1,int c2){//加入大哥
int f1=find(c1),f2=find(c2);
if(f1!=f2) f[f1]=f2;
}
int main(){
cin>>n>>m>>p;
for(int i=1;i<=n;i++){
f[i]=i;
}
for(int i=1;i<=m;i++){
cin>>x>>y;
join(x,y);
}
for(int i=1;i<=p;i++){
cin>>x>>y;
if(find(x)==find(y)){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
return 0;
}