一、例题引入
【模板】并查集
题目描述
如题,现在有一个并查集,你需要完成合并和查询操作。
输入格式
第一行包含两个整数 $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
样例输入 #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 \le 10$,$M \le 20$。
对于 $70%$ 的数据,$N \le 100$,$M \le 10^3$。
对于 $100%$ 的数据,$1\le N \le 10^4$,$1\le M \le 2\times 10^5$,$1 \le X_i, Y_i \le N$,$Z_i \in { 1, 2 }$。
二、题目分析
可以看出,这是一道判断连通性的题目。因此,我们可以使用数据结构“并查集”来实现。
三、算法过程
我们可以将“将两个点连在一起”的操作转换为“将一个点认另一个点为父亲”的操作
初始时,每个点的父亲都为它本身。
在查询时,我们只需知道两个点的“老祖宗”是否是同一个点,即可判断两个点是否连通。
四、路径压缩
我们在查询“老祖宗”的过程中,可以动态更新“父亲”,这就是路径压缩
五、代码实现
#include<bits/stdc++.h>
#define N 10009
using namespace std;
int n,m;
int fa[N];
int find(int a){
if(fa[a]==a)
return a;
return fa[a]=find(fa[a]);
}
void unite(int a,int b){
fa[find(a)]=find(b);
}
int main(){
cin>>n>>m;
int i;
for(i=1;i<=n;i++)
fa[i]=i;
int z,x,y;
for(i=1;i<=m;i++){
cin>>z>>x>>y;
if(z==1){
unite(x,y);
}
else{
if(find(x)==find(y))
cout<<"Y"<<endl;
else
cout<<"N"<<endl;
}
}
return 0;
}
标签:10,le,int,查集,笔记,学习,fa,find
From: https://www.cnblogs.com/ACTVnews-JosefOckmode/p/18588237