procedureDfs(cnt,fa:longint);//现在的节点cnt,父亲fa var i:longint; begin dep[cnt]:=dep[fa]+1; //更新深度 get[cnt,0]:=fa; //get的fa,前面已讲 i:=0; repeat inc(i); //方++ get[cnt,i]:=get[get[cnt,i-1],i-1]; //神奇de公式 until lg[i]>dep[cnt]; //忘了介绍lg[i]=2的i次方,要预处理,大概i到21左右 i:=head[cnt]; //链式前向星 while i<>0do begin if gt[i]<>fa then Dfs(gt[i],cnt); //其他连边 i:=next[i]; end; end;
function Find(x_,y_:longint):longint; //两个节点 x_,y_ var i,x,y,t:longint; begin x:=x_; y:=y_; if dep[x_]<dep[y_] then //交换深度,使y在高处 begin x:=y_; y:=x_; end; for i:=21 downto 0 do //一定是downto!!!(看前面事例) if (dep[y]<=dep[x]-lg[i]) then //让x跳到y处 x:=get[x,i]; if x=y then exit(x); //如果x已经是y了,那么y就是祖先了 for i:=21 downto 0 do //一定是downto!! if get[x,i]<>get[y,i] then //说明一点,如果我跳过了怎么办?那么我们就跳到祖先的下面(反正任何数都可以被2的n次方相加,对不对),然后直接返回此节点的父亲就得了 begin x:=get[x,i]; //大家一起跳 y:=get[y,i]; end; exit(get[x,0]); end;
var get:array[-1..500010,0..21] of longint; num,gt,head,next:array[-1..5000010] of longint; lg:array[0..21] of longint; dep:array[-1..500010] of longint; i,n,m,l,r,root:longint;
procedureMain; var i:longint; begin read(n,m,root); dec(n); for i:=1to n do begin read(l,r); gt[2*i]:=r; next[2*i]:=head[l]; head[l]:=2*i; gt[2*i-1]:=l; next[2*i-1]:=head[r]; head[r]:=2*i-1; end; lg[0]:=1; for i:=1to21do lg[i]:=lg[i-1]*2; end;
functionFind(x_,y_:longint):longint; var i,x,y,t:longint; begin x:=x_; y:=y_; if dep[x_]<dep[y_] then begin x:=y_; y:=x_; end; for i:=21downto0do if (dep[y]<=dep[x]-lg[i]) then x:=get[x,i]; if x=y then exit(x); for i:=21downto0do if get[x,i]<>get[y,i] then begin x:=get[x,i]; y:=get[y,i]; end; exit(get[x,0]); end;
procedureDfs(cnt,fa:longint); var i:longint; begin dep[cnt]:=dep[fa]+1; get[cnt,0]:=fa; i:=0; repeat inc(i); get[cnt,i]:=get[get[cnt,i-1],i-1]; until lg[i]>dep[cnt]; i:=head[cnt]; while i<>0do begin if gt[i]<>fa then Dfs(gt[i],cnt); i:=next[i]; end; end;
procedureAnswer; begin read(l,r); writeln(Find(l,r)); end;
begin Main; Dfs(root,-1); for i:=1to m do Answer; end.