<pre name="code" class="delphi">{
效率 预处理 O(nlog(n)) 查询 O(log(n))
优点:能够记录路径、
缺点:没有LCA转RMQ的ST算法快
}
program pro;
var
link:array[0..100]of record ke,po,ne,pr:longint; end;
deep,st:array[0..100]of longint;
fa:array[0..100,0..20]of longint;
n,m,tot,i,j:longint;
procedure make(u,v:longint);//链表存储树
begin
inc(tot);
link[tot].ne:=st[u];
st[u]:=tot;
link[tot].po:=v;
end;
procedure swap(var x,y:longint);
var
kk:longint;
begin
kk:=x; x:=y; y:=kk;
end;
procedure init;
var
u,v,c,ii:longint;
begin
readln(n);
for ii:=1 to n-1 do
begin
readln(u,v);
make(u,v);
end;
end;
function find(x,y:longint):longint;//查找 效率 O(log(n))
var
temp,ii:longint;
begin
if x=y then exit(x);
if deep[x]<deep[y] then swap(x,y);//先将两点移到同一深度
temp:=deep[x]-deep[y];
ii:=0;
while temp>0 do
begin
if temp and 1=1 then x:=fa[x,ii];
temp:=temp shr 1;
inc(ii);
end;
if x=y then exit(x);
ii:=0;
while x<>y do <span style="white-space:pre"> </span>//以 2^ii 向上查找
begin
if (fa[x,ii]<>fa[y,ii])or((fa[x,ii]=fa[y,ii])and(ii=0)) then
begin //到每一个 2^ii 的父亲结点 如果 下一个2^k结点相等则dec(ii)查找当前结点距离2^k的父亲结点
x:=fa[x,ii]; y:=fa[y,ii];
inc(ii);
end
else dec(ii);
end;
exit(x);
end;
procedure ready(x:longint); //预处理
var
temp,po,son,ii:longint;
begin
temp:=st[x];
while temp<>0 do
begin
son:=link[temp].po;
fa[son,0]:=x;
po:=x;
deep[son]:=deep[x]+1;
ii:=0;
while fa[po,ii]<>0 do
begin
fa[son,ii+1]:=fa[po,ii];//递归求出距离当前结点2^ii的父亲节点
po:=fa[po,ii];
inc(ii);
end;
ready(son);
temp:=link[temp].ne;//向下递归求解
end;
end;
begin
assign(input,'test.in');reset(input);
assign(output,'test.out');rewrite(output);
init;
ready(1);
for i:=1 to n do
for j:=1 to n do
writeln(i,' ',j,' ',find(i,j));
close(input);
close(output);
end.
Pascal 倍增求LCA
最新推荐文章于 2018-06-10 18:31:15 发布