http://www.lydsy.com/JudgeOnline/problem.php?id=1787
http://www.lydsy.com/JudgeOnline/problem.php?id=1832
给定一棵树,每次询问3个点到某一点的最小距离和
3个点,其实任意两点间有lca,而且最多有3个不同lca(事实上最多是2个),这样的话3种情况比大小即可
事实是:3个点两两lca最多有两个不同lca,集合节点为不同于其他两个的那个点
这个我们yy一下就好了...(T_T)
const
maxn=500005;
var
w:array[0..3*maxn,1..2]of longint;
dep,t:array[0..maxn]of longint;
st:array[0..maxn,0..20]of longint;
i,j,k:longint;
n,m,len,a,b,c,d,e,f,v,tt,head,tail,maxd,ans:longint;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0
then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
function lca(a,b:longint):longint;
var i:longint;
begin
if dep[a]>dep[b] then begin i:=a; a:=b; b:=i; end;
for i:=trunc(ln(maxd)/ln(2))+1 downto 0 do
if dep[st[b,i]]>=dep[a]
then b:=st[b,i];
if a=b then exit(a);
for i:=trunc(ln(maxd)/ln(2))+1 downto 0 do
if st[a,i]<>st[b,i]
then begin a:=st[a,i]; b:=st[b,i]; end;
exit(st[a,0]);
end;
function dis(a,b:longint):longint;
var k:longint;
begin
k:=lca(a,b);
exit(dep[a]+dep[b]-dep[k]*2);
end;
begin
readln(n,m); len:=n+1;
for i:=1 to n-1 do
begin
readln(a,b);
init(a,b); init(b,a);
end;
fillchar(dep,sizeof(dep),0);
dep[1]:=1; t[1]:=1; head:=1; tail:=2; maxd:=1;
while head<tail do
begin
v:=t[head]; inc(head); tt:=w[v,2];
while tt<>0 do
begin
if dep[w[tt,1]]=0 then begin
dep[w[tt,1]]:=dep[v]+1; t[tail]:=w[tt,1]; inc(tail);
st[w[tt,1],0]:=v;
if dep[v]+1>maxd then maxd:=dep[v]+1;
end;
tt:=w[tt,2];
end;
end;
for j:=1 to trunc(ln(maxd)/ln(2))+1 do
for i:=1 to n do
st[i,j]:=st[st[i,j-1],j-1];
for i:=1 to m do
begin
readln(a,b,c);
d:=lca(a,b); e:=lca(a,c); f:=lca(b,c);
if d=e then k:=f
else if e=f then k:=d
else k:=e;
ans:=dis(a,k)+dis(b,k)+dis(c,k);
writeln(k,' ',ans);
end;
end.