您的位置:首页 > 其它

uva11987 并查集小技巧

2013-05-06 20:21 169 查看
大意:维护一种数据结构,支持 几乎是常数级别的 集合合并、将一个元素转移到另一个集合、询问每个集合的和与元素个数。

思路:使用并查集,转移元素时留下一个空节点,同时增加一个节点,将p转移到新根。用pos[p]记录p数字现在的实际位置即可。

program p11987;

Var
n,m,i,p,q,op,top:longint;
f,c,pos,s:array[0..500002] of longint;

Function find(P:longint):longint;
begin
if f[p]=p then exit(p);
f[p]:=find(f[p]);
exit(f[p]);
end;

Procedure union(p,q:longint);
var
fp,fq:longint;
begin
fp:=find(pos[p]);
fq:=find(pos[q]);
if fp=fq then exit;
if c[fp]<c[fq] then
begin
f[fp]:=fq;
inc(c[fq],c[fp]);
inc(s[fq],s[fp]);
end else
begin
f[fq]:=fp;
inc(c[fp],c[fq]);
inc(s[fp],s[fq]);
end;
end;

Procedure move(p,q:longint);inline;
var
fp,fq:longint;
begin
fp:=find(pos[p]);
fq:=find(pos[q]);
if fp=fq then exit;
dec(c[fp]);
dec(s[fp],p);
inc(c[fq]);
inc(s[fq],p);
inc(top);
pos[p]:=top;
f[pos[p]]:=fq;
end;

begin
while not eof do
begin
readln(n,m);top:=n;
for i:=1 to n do begin f[i]:=i;c[i]:=1;pos[i]:=i;s[i]:=i; end;
while m>0 do
begin
dec(m);
read(op);
case op of
1:begin
readln(p,q);
union(p,q);
end;
2:begin
readln(p,q);
move(p,q);
end;
3:begin
readln(p);
writeln(c[find(pos[p])],' ',s[find(pos[p])]);
end;
end;
end;
end;

end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: