【NOIP2012模拟10.27】祖孙询问
Description
已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。
Input
输入第一行包括一个整数n表示节点个数。
接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。
第n+2行是一个整数m表示询问个数。
接下来m行,每行两个正整数x和y。
Output
对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0。
题解
DFS序以及各种求LCA算法均可秒杀此题。
代码
type
arr=record
y,next:longint;
end;
var
n,m,nm,n_1:longint;
ls,h:array [0..40001] of longint;
go:array [0..40001,0..20] of longint;
e:array [0..80001] of arr;
procedure add(o,p:longint);
begin
inc(nm);
with e[nm] do
begin
y:=p; next:=ls[o]; ls[o]:=nm;
end;
inc(nm);
with e[nm] do
begin
y:=o; next:=ls[p]; ls[p]:=nm;
end;
end;
procedure init;
var
i,x,y:longint;
begin
nm:=0;
readln(n);
for i:=1 to n do
begin
readln(x,y);
if y=-1 then n_1:=x
else add(x,y);
end;
end;
procedure dfs(x:longint);
var
i:longint;
begin
for i:=1 to 15 do
begin
if h[x]<(1 shl i) then break;
go[x,i]:=go[go[x,i-1],i-1];
end;
i:=ls[x];
while i>0 do
with e[i] do
begin
if y<>go[x,0] then
begin
h[y]:=h[x]+1; go[y,0]:=x;
dfs(y);
end;
i:=next;
end;
end;
function LCA(x,y:longint):longint;
var
t,i:longint;
begin
if h[x]<h[y] then
begin
t:=x; x:=y; y:=t;
end;
t:=h[x]-h[y];
for i:=15 downto 0 do
if (t and (1 shl i))<>0 then x:=go[x,i];
for i:=15 downto 0 do
if go[x,i]<>go[y,i] then
begin
x:=go[x,i];
y:=go[y,i];
end;
if x=y then exit(x);
exit(go[x,0]);
end;
procedure main;
var
i,x,y,t:longint;
begin
dfs(n_1);
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.