HDU2586
要注意只有简单边相连的图是一棵树,树有n-1条边
倍增之前要先存双向边,以任意顶点为根(比如1)dfs遍历确定树。
倍增前求f[i,j]时先赋值为-1便于判断f[ij-1]祖先存不存在
倍增时先将两个点调至同一高度(注意最后的微调每次只上升一个高度)
program hdu2586;
const maxm=15;
var i,j,ans,t,l1,l,n,m,x,y,z:longint;
f,g:array[0..40000,0..15]of longint;
vis:array[0..40000]of boolean;
edge:array[1..80000,1..3]of longint;
deep:array[-1..40000]of longint;
head:array[1..40000]of longint;
procedure dfs(u,de:longint);//buildtree_root=1
var p:longint;
begin
vis[u]:=true;
deep[u]:=de;
p:=head[u];
while p<>-1 do
begin
if vis[edge[p,1]]=false then
begin
g[edge[p,1],0]:=edge[p,2];
f[edge[p,1],0]:=u;
dfs(edge[p,1],de+1);
end;
p:=edge[p,3];
end;
end;
procedure make;//倍增
var j,i:longint;
begin
for j:=1 to maxm do
for i:=1 to n do
if f[i,j-1]<>-1 then
begin
f[i,j]:=f[f[i,j-1],j-1];
g[i,j]:=g[i,j-1]+g[f[i,j-1],j-1];
end;
end;
procedure find(x,y:longint);
var tmp,i:longint;
begin
if deep[x]deep[y] then
begin
ans:=ans+g[x,i];
x:=f[x,i];
end;
while deep[x]>deep[y] do
begin
ans:=ans+g[x,0];x:=f[x,0];
end;
if x=y then exit;
for i:=maxm downto 1 do
if f[x,i]<>f[y,i] then
begin
ans:=ans+g[x,i]+g[y,i];
x:=f[x,i];
y:=f[y,i];
end;
while x<>y do
begin
ans:=ans+g[x,0]+g[y,0];
x:=f[x,0];
y:=f[y,0];
end;
end;
begin
read(t);
for l1:=1 to t do
begin
read(n,m);
for i:=1 to n do head[i]:=-1;
for i:=1 to n-1 do
begin
read(x,y,z);
l:=l+1;
edge[l,1]:=y;
edge[l,2]:=z;
edge[l,3]:=head[x];
head[x]:=l;
l:=l+1;
edge[l,1]:=x;
edge[l,2]:=z;
edge[l,3]:=head[y];
head[y]:=l;
end;
fillchar(f,sizeof(f),0);//father
fillchar(g,sizeof(g),0);//distence
fillchar(vis,sizeof(vis),false);
for j:=0 to maxm do
for i:=1 to n do
f[i,j]:=-1;//f[1,0]:=-1;g[1,0]:=0;
dfs(1,1);
make;
for i:=1 to m do
begin
ans:=0;
read(x,y);
find(x,y);
writeln(ans);
end;
end;
end.