题目:
已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。
分析:
DFS序以及各种求LCA算法均可秒杀此题。
DFS遍历树,记录每个点X的第一次访问时间st[x]和最后一次访问时间ed[x],若y在以X为根的子树中,则一定有st[x]<st[y]<ed[y]<ed[x]。
附上代码:
const
maxn=40000;
type
arr=record
y,next:longint;
end;
var
n,m,test,temp:longint;
a,b:array [0..maxn] of longint;
cristine:array [0..maxn,0..20] of longint;
elist:array [0..maxn*2] of arr;
procedure add(x1,y1:longint);
begin
inc(test);
with elist[test] do
begin
y:=y1;
next:=a[x1];
a[x1]:=test;
end;
inc(test);
with elist[test] do
begin
y:=x1;
next:=a[y1];
a[y1]:=test;
end;
end;
procedure init;
var
i,x,y:longint;
begin
test:=0;
readln(n);
for i:=1 to n do
begin
readln(x,y);
if y=-1 then
temp:=x
else add(x,y);
end;
end;
procedure dfs(x:longint);
var
i:longint;
begin
for i:=1 to 15 do
begin
if b[x]<(1 shl i) then
break;
cristine[x,i]:=cristine[cristine[x,i-1],i-1];
end;
i:=a[x];
while i>0 do
with elist[i] do
begin
if y<>cristine[x,0] then
begin
b[y]:=b[x]+1;
cristine[y,0]:=x;
dfs(y);
end;
i:=next;
end;
end;
function lca(x,y:longint):longint;
var
t,i:longint;
begin
if b[x]<b[y] then
begin
t:=x;
x:=y;
y:=t;
end;
t:=b[x]-b[y];
for i:=15 downto 0 do
if (t and (1 shl i))<>0 then
x:=cristine[x,i];
for i:=15 downto 0 do
if cristine[x,i]<>cristine[y,i] then
begin
x:=cristine[x,i];
y:=cristine[y,i];
end;
if x=y then
exit(x);
exit(cristine[x,0]);
end;
procedure main;
var
i,x,y,t:longint;
begin
dfs(temp);
readln(m);
for i:=1 to m do
begin
readln(x,y);
if x=y then
writeln('0')
else
begin
t:=lca(x,y);
if t=x then
writeln('1')
else
if t=y then
writeln('2')
else
writeln('0');
end;
end;
end;
begin
init;
main;
end.
maxn=40000;
type
arr=record
y,next:longint;
end;
var
n,m,test,temp:longint;
a,b:array [0..maxn] of longint;
cristine:array [0..maxn,0..20] of longint;
elist:array [0..maxn*2] of arr;
procedure add(x1,y1:longint);
begin
inc(test);
with elist[test] do
begin
y:=y1;
next:=a[x1];
a[x1]:=test;
end;
inc(test);
with elist[test] do
begin
y:=x1;
next:=a[y1];
a[y1]:=test;
end;
end;
procedure init;
var
i,x,y:longint;
begin
test:=0;
readln(n);
for i:=1 to n do
begin
readln(x,y);
if y=-1 then
temp:=x
else add(x,y);
end;
end;
procedure dfs(x:longint);
var
i:longint;
begin
for i:=1 to 15 do
begin
if b[x]<(1 shl i) then
break;
cristine[x,i]:=cristine[cristine[x,i-1],i-1];
end;
i:=a[x];
while i>0 do
with elist[i] do
begin
if y<>cristine[x,0] then
begin
b[y]:=b[x]+1;
cristine[y,0]:=x;
dfs(y);
end;
i:=next;
end;
end;
function lca(x,y:longint):longint;
var
t,i:longint;
begin
if b[x]<b[y] then
begin
t:=x;
x:=y;
y:=t;
end;
t:=b[x]-b[y];
for i:=15 downto 0 do
if (t and (1 shl i))<>0 then
x:=cristine[x,i];
for i:=15 downto 0 do
if cristine[x,i]<>cristine[y,i] then
begin
x:=cristine[x,i];
y:=cristine[y,i];
end;
if x=y then
exit(x);
exit(cristine[x,0]);
end;
procedure main;
var
i,x,y,t:longint;
begin
dfs(temp);
readln(m);
for i:=1 to m do
begin
readln(x,y);
if x=y then
writeln('0')
else
begin
t:=lca(x,y);
if t=x then
writeln('1')
else
if t=y then
writeln('2')
else
writeln('0');
end;
end;
end;
begin
init;
main;
end.