后续
我改动的地方没什么实际意义,原因的话原博主在评论区详细说明了。请直接参考原始代码
参考
代码参考全网最通俗易懂并查集讲解
部分改动声明
自认为代码有少许瑕疵,更改了小部分,用“//补充”标记出来了,欢迎大家批评指正
代码
#include <bits/stdc++.h>
using namespace std;
//#define int long long
/*
洛谷 P3367 【模板】并查集
https://www.luogu.com.cn/problem/P3367
代码参考全网最易懂并查集讲解:
https://blog.csdn.net/the_ZED/article/details/105126583
自认为代码有少许瑕疵,更改了小部分,用“//补充”标记出来了,欢迎大家批评指正
*/
const int SIZE=1e4+10; //指定并查集所能包含元素的个数(由题意决定)
int pre[SIZE]; //存储每个结点的前驱结点
//补充
//由于命名冲突,rank改成了rankIndex
int rankIndex[SIZE]; //树的高度,注意树的高度主要与某个集合的根父节点有关
void init(int n) //初始化函数,对录入的 n个结点进行初始化
{
//补充
for(int i = 1; i <= n; i++){ //针对下标从1开始的情况
pre[i] = i; //每个结点的上级都是自己
rankIndex[i] = 1; //每个结点构成的树的高度为 1
}
}
/*
int find(int x) //查找结点 x的根结点
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,则 x为根结点
return find(pre[x]); //递归查找
}
*/
// 在查找根节点的同时完成路径压缩
int find(int x) //改进查找算法:完成路径压缩,将 x的上级直接变为根结点,那么树的高度就会大大降低
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,即 x为根结点
/*
改得没意义
//补充
if(rankIndex[x]>2){ //路径压缩:将所有高度大于2的节点全部转换为高度为2的节点
rankIndex[x]=2;
}
*/
return pre[x] = find(pre[x]); //此代码相当于先找到根结点 rootx,然后 pre[x]=rootx
}
bool isSame(int x, int y) //判断两个结点是否连通
{
return find(x) == find(y); //判断两个结点的根结点(即代表元)是否相同
}
//补充:
//疑惑:在合并不同集合的节点时,如果节点x作为某节点的子节点,那么,以节点x为父节点的节点以及节点x都要增加rankIndex的值
//缺点:这个步骤复杂度为O(n),会超时
//解答:由于rankIndex集合主要与某个集合的根父节点有关,下面各个节点的rankIndex可以不用管,
//而每次在 调用改进find方法 时,rankIndex的大小都会被更新,
//rankIndex的范围都在1~2之间,因此每次各个要合并的子集的高度都为1~2之间。
//因此,调用改进find方法 rankIndex 大小比较无需更新其子节点的rankIndex
bool join(int x,int y)
{
x = find(x); //寻找 x的代表元
y = find(y); //寻找 y的代表元
if(x == y) return false; //如果 x和 y的代表元一致,说明他们共属同一集合,则不需要合并,返回 false,表示合并失败;否则,执行下面的逻辑
if(rankIndex[x] > rankIndex[y])
pre[y]=x; //如果 x的高度大于 y,则令 y的上级为 x (为了减少各个子树之间的高度相对差)
else //否则
{
if(rankIndex[x]==rankIndex[y])
rankIndex[y]++; //如果 x的高度和 y的高度相同,则令 y的高度加1
pre[x]=y; //让 x的上级为 y
}
return true; //返回 true,表示合并成功
}
void read(){
int z,x,y,//操作,每次操作的两个元素
n,//元素个数
m;//操作个数
cin>>n>>m;
init(n);
for(int i=0;i<m;i++){
cin>>z>>x>>y;
if(z==1){
join(x,y);
}else{
bool isSameGroup=isSame(x,y);
cout<<(isSameGroup?"Y":"N")<<endl;
}
}
}
int main() {
read();
return 0;
}