三个点,两两找lca,最后结果一定在这三个点中出,都算出来比较一下就可以了(两个点的最短距离+第三个点到lca的距离)
脑残:建图的时候一定要乖乖的建,不要建成n-1条有向边,会不联通的 orz orz orz
var
n,m,ans1,root,pos:longint;
l,a,b,c,ans2,tt,t:longint;
ta,tb,tc :longint;
last,d :array[0..500010] of longint;
pre,other :array[0..500010] of longint;
vis :array[0..500010] of boolean;
jump :array[0..500010,0..20] of longint;
i,j :longint;
procedure connect(x,y:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
end;
procedure swap(var a,b:longint);
var
c:longint;
begin
c:=a;a:=b;b:=c;
end;
procedure dfs(x:longint);
var
p,q:longint;
begin
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if not vis[p] then
begin
vis[p]:=true;
d[p]:=d[x]+1;
jump[p,0]:=x;
dfs(p);
end;
q:=pre[q];
end;
end;
function lca(x,y:longint):longint;
var
i,j:longint;
t:longint;
begin
t:=0;
if (d[x]>d[y]) then swap(x,y);
//
for j:=0 to 19 do
if ((1<<j) and (d[y]-d[x])<>0) then
begin
inc(t,1<<j);
y:=jump[y,j];
end;
//
if (x<>y) then
begin
for j:=19 downto 0 do
if (jump[x,j]<>jump[y,j]) then
begin
inc(t,1<<j);inc(t,1<<j);
y:=jump[y,j];
x:=jump[x,j];
end;
inc(t,2);
pos:=jump[x,0];
end else pos:=x;
//
exit(t);
end;
begin
read(n,m);
for i:=1 to n-1 do
begin
read(a,b);
connect(a,b);
vis[b]:=true;
end;
//
for i:=1 to n do if not vis[i] then break;
root:=i;
for i:=1 to n do vis[i]:=false;
d[root]:=1;vis[root]:=true;
dfs(root);
//
for j:=1 to 19 do
for i:=1 to n do jump[i,j]:=jump[jump[i,j-1],j-1];
//
for i:=1 to m do
begin
read(a,b,c);
ans1:=maxlongint;
//
tt:=lca(a,b);
t:=pos;
tt:=tt+lca(pos,c);
if (tt<ans1) then
begin
ans1:=tt;ans2:=t;
end;
//
tt:=lca(a,c);
t:=pos;
tt:=tt+lca(pos,b);
if (tt<ans1) then
begin
ans1:=tt;ans2:=t;
end;
//
tt:=lca(b,c);
t:=pos;
tt:=tt+lca(pos,a);
if (tt<ans1) then
begin
ans1:=tt;ans2:=t;
end;
//
writeln(ans2,' ',ans1);
end;
end.
——by Eirlys