方法1:
用编号最小的元素标记所在集合;
定义一个数组 set[1..n] ,其中set[i] 表示元素i 所在的集合;
O(1):
find1(x)
{
return set[x];
}
O(n)
Merge1(a,b)
{ i = min(a,b);
j = max(a,b);
for (k=1; k<=N; k++) {
if (set[k] == j)
set[k] = i;
}
}
方法2;
每个集合用一棵“有根树”表示定义数组 set[1..n]
set[i] = i , 则i表示本集合,并是集合对应树的根
set[i] = j, j != i, 则 j 是 i 的父节点.
find2(x)
{
r = x;
while (set[r] != r)
r = set[r];
return r;
} //O(n)
merge2(a, b)
{
if (a<b)
set[b] = a;
else
set[a] = b;
}//O(1)
带路径压缩的查找算法
第一步,找到根结点
第二步,修改查找路径上的所有节点,将它们都指向根结点
find3(x)
{
r = x;
while (set[r] <> r) //循环结束,则找到根节点
r = set[r];
i = x;
while (i <> r) //本循环修改查找路径中所有节点
{
j = set[i];
set[i] = r;
i = j;
}
}
//并查集练习
HDOJ-1558 Segment set
HDOJ-1811 Rank of Tetris
HDOJ-1829 A Bug's Life
HDOJ-1198 Farm Irrigation
ZOJ 2740