题目大意:
给出T组数据,每组有N个点,N-1条边,构成一颗树,给出一对点[x,y],问x和y的最近公共祖先是多少。
2<=N<=10,000
题解:
这题是LCA的模版题吧。。
x,y的最近公共祖先,你可以这么想,x到根节点的路径跟y到根节点的路径的第一个交点z就是了。
tarjan离线做法,因为可以在一次遍历中把查询解决,所以时间复杂度为O(N+Q)
tarjan解释这种东西想了很久觉得,还是意会吧…
我表示有点难以表述……
代码:
const
maxn=10000;
var
f,list,next,x,y:array [0..maxn+1] of longint;
v:array [0..maxn+1] of boolean;
i,n,p,q,t:longint;
flag:boolean;
function find(x:longint):longint;
begin
if f[x]=x then exit(x);
f[x]:=find(f[x]);
exit(f[x]);
end;
procedure dfs(x:longint);
var
i:longint;
begin
v[x]:=true;
if flag then exit;
if (v[p]) and (v[q]) then
begin
if x=p then writeln(find(q))
else writeln(find(p));
flag:=true;
exit;
end;
i:=list[x];
while i>0 do
begin
dfs(y[i]);
f[find(y[i])]:=x;
i:=next[i];
end;
end;
procedure tarjan;
var
i,j:longint;
begin
for i:=1 to n do
begin
if not(v[i]) then j:=i;
f[i]:=i;
end;
fillchar(v,sizeof(v),false);
flag:=false;
dfs(j);
end;
begin
readln(t);
while t>=1 do
begin
readln(n);
fillchar(list,sizeof(list),0);
fillchar(v,sizeof(v),false);
for i:=1 to n-1 do
begin
readln(x[i],y[i]);
next[i]:=list[x[i]];
list[x[i]]:=i;
v[y[i]]:=true;
end;
readln(p,q);
tarjan;
dec(t);
end;
end.