/*这个源自哪位大牛实在不知,若原作者觉得出现在这里不合适,可在评论栏留言,鄙人当立即删去。*/
{
并查集模块基本思想:以树表示集合,用树的根作为集合的标识,同一棵树的根是相同的。
时间复杂度:
查找:O(h)
合并:O(h)
理想情况下:h=log(n)
}
const
maxn=1000;//最大节点数
var
f, h: array[1..maxn]: of longint; {f[i]:i的父亲,h[i]:i为根的子树深度}
procedure makeset;//初始化
var
i:longint;
begin
for i:=1 to n do //初始化每个节点均为一棵独立的树
begin
f[i]:=i;
h[i]:=1;
end;
end;
function find(x):longint;//返回x节点所在的树的根
begin
if f[x]=x then //x本来就是根
find:=x
else begin //否则返回x父亲的根
f[x]:=find(f[x]); //路径压缩,让x及所有祖先节点全部指向根
find:=f[x];
end;
end;
procedure merge(a,b);把a,b两个节点所在的树合并
var
ra,rb:longint;
begin
ra:=find(a);
rb:=find(b);
if h[ra]<h[rb] then //把小树合并到大树上
f[ra]:=rb;
else begin
f[rb]:=ra;
if h[ra]=h[rb] then inc(h[ra]);//维护新树的深度
end;
end;