并查集(Union Find)是一种用于处理不相交集合的数据结构。它支持两个主要操作:合并(Union)和查找(Find)。
在并查集中,每个元素都有一个父节点指向它所属的集合的根节点。如果某个元素的父节点指向自身,则表示该元素为集合的根节点。
合并操作将两个集合合并为一个集合,即将一个集合的根节点的父节点指向另一个集合的根节点。这可以通过查找两个元素所属集合的根节点,并将其中一个的根节点的父节点指向另一个根节点来实现。
查找操作用于确定某个元素所属的集合。它通过递归地查找元素的父节点,直到找到根节点为止。根节点即为集合的代表元素。
并查集常用于解决一些集合类问题,比如判断两个元素是否属于同一个集合、求解连通分量等。它的时间复杂度取决于树的高度,在最坏情况下可能达到O(n)。
C++中可以使用数组来实现并查集。假设有n个元素,可以使用一个大小为n的数组parent来保存每个元素的父节点。初始时,每个元素的父节点都指向自身。
可以把这个过程想象成帮派火并,两个帮派合并的时候就让一帮人的上司变成另一帮人的上司,然后就变成了一群人。查找两个人是不是同一个帮派的时候只需要看两个人的上司是不是同一个就可以了。
以下是一个基本的C++实现:
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
typedef long long ll;
int n,m,f[1000001],a,b;
char temp;
int find(int a){
while(f[a]!=a) a=f[a];
return f[a];
}
int main(){
scanf("%d%d",&n,&m);
rep(i,1,n) f[i]=i;
while(m--){
cin>>temp>>a>>b;
int aa=find(a),bb=find(b);
if(temp=='M') f[aa]=bb;//合并
else{//查找
if(aa==bb) printf("YES\n");
else printf("NO\n");
}
}
}
在上面的代码中,find函数使用路径压缩优化来减小树的高度。f数组来表示合并时哪个集合作为父节点。
这只是一个简单的并查集实现,还可以根据具体需求进行改进和扩展。