版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
class DisjointSet {
public:
static const int MAXN = 1e3+100;
int n;
int root[MAXN];
DisjointSet( ) { };
DisjointSet( int _n ) : n(_n) { };
void INI ( int n ) {
this->n = n;
for ( int i = 1; i <= n; ++i ) root[i] = i;
}
int GET ( int x ) {
return root[x]==x ? x : root[x]=GET( root[x] );
}
bool MERGE ( int x, int y ) {
int rx = GET( x ), ry = GET( y );
if ( rx==ry ) return false;
root[ry] = rx; return true;
}
}ds;
路径压缩详解博客
从上到下三份 AC 代码 分别对应
非递归压缩路径,
递归未压缩路径,
递归压缩路径
在放上 非递归压缩路径 和 非递归未压缩路径
时间差距还是比较明显的
放上寻根函数的四个版本
// 递归压缩路径
int GET ( int x ) {
return root[x]==x ? x : root[x]=GET( root[x] );
}
// 递归不压缩路径
int GET ( int x ) {
return root[x]==x ? x : GET( root[x] );
}
// 非递归不压缩路径
int GET ( int x ) {
while ( x != root[x] )
x = root[x];
return x;
}
// 非递归压缩路径
int GET ( int p){
while ( p != root[p] ) {
root[p] = root[root[p]];
p = root[p];
}
return p;
}
如果p元素的父亲指针指向的不是自己,说明p并不是集合中的根元素,还需要一直向上查找和路径压缩
p元素不再选择原来的父亲节点,而是直接选择父亲节点的父亲节点来做为自己新的一个父亲节点
p压缩完毕后且p并不是根节点,p变成p新的父节点继续进行查找和压缩的同时操作