一般而言,并查集算法有两种:
- 路径压缩(通常情况下会快一些)
- 按秩合并
由于路径压缩很常用,我只是简单贴个代码,今天主讲按秩合并
int find (int x) { return x==fa[x]?x:fa[x]=find(fa[x]); }
没错,这就是路径压缩的装13写法,大概就是 fa [ i ]存的是 i 的祖先(不是daddy,是daddy的daddy的daddy的daddy……)
那么按秩合并,秩是什么呢?其实秩就是树高
给每个点一个秩(初始值为1),每次合并的时候都用秩小的指向秩大的,可以保证树高最高为log(n)
然后更新 rank ( rank[x]指的是点x秩),在一次合并后,假设是点x和点y,x的秩小,就将 fa[x] 指向 y,然后将 rank[y] 的与 rank[x+1] 取 max
因为rank[x]为区间x的高,将它连向y之后,y的树高就会是x的树高+1,当然也可能y在另一边树高更高,所以取max
到这里 按秩合并 就结束啦,是不是很简单啊~下面上一波代码
int getfa(int x){
if(x==fa[x]) return x;
return getfa(fa[x]); //这个和路径压缩的find是一样的
}
void merge(int x,int y){
int fx=getfa(x);
int fy=getfa(y);
if(rank[fx]<rank[fy]) swap(fx,fy);
fa[fy]=fx;
rank[fx]=max(rank[fy]+1,rank[fx]);
}