洛谷 P3367 【模板】并查集 C++
题目背景
本题数据范围已经更新到 1≤N≤2×10 5 ,1≤M≤10 6 。
题目描述
如题,现在有一个并查集,你需要完成合并和查询操作。
输入格式
第一行包含两个整数 N,M ,表示共有 N 个元素和 M 个操作。
接下来 M 行,每行包含三个整数 Z i ,X i ,Y i 。
当 Z i =1 时,将 X i 与 Y i 所在的集合合并。
当 Z i =2 时,输出 X i 与 Y i 是否在同一集合内,是的输出 Y ;否则输出 N 。
输出格式
对于每一个 Z i =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
说明/提示
对于 15% 的数据,N≤10,M≤20。
对于 35% 的数据,N≤100,M≤10 3 。
对于 50% 的数据,1≤N≤10 4 ,1≤M≤2×10 5 。
对于 100% 的数据,1≤N≤2×10 5 ,1≤M≤10 6 ,1≤X i ,Y i ≤N,Z i ∈{1,2}。
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int fa[N];//并查集父节点数组,fa[i]表示i的父节点
void init(int n)//初始化并查集,每个元素的父节点指向自己
{
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
}
int find(int x)//带路径压缩的查找
{
if(x==fa[x])//找到根节点
{
return x;
}else{
fa[x]=find(fa[x]);//路径压缩:将当前节点的父节点直接指向根
return fa[x];//返回根节点
}
}
void unionn(int i,int j)//合并
{
int i_fa=find(i);//找到i的根节点
int j_fa=find(j);//找到j的根节点
fa[i_fa]=j_fa;//将i的根节点指向j的根节点
}
int main()
{
int n,m;
cin>>n>>m;
init(n);
for(int i=1;i<=m;i++)
{
int z,x,y;
cin>>z>>x>>y;
if(z==1)
{
unionn(x,y);
}else{
if(find(x)==find(y))//判断是否属于同一集合
{
cout<<"Y"<<endl;
}else{
cout<<"N"<<endl;
}
}
}
return 0;
}