Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
Input
输入文件kom.in中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
Output
在输出文件kom.out中输出该商人旅行的最短时间。
Sample Input
5
1 2
1 5
3 5
4 5
4
1
3
2
5
Sample Output
7
题解
lca的模板题,先跑一次记录没给点的深度,(s,t)的最短距离是d[s]+d[t]-2*d[fa(s,t)]
~~o(>_<)o ~~,第一次做,多打几遍就会了。
代码
type
ab=^node;
node=record
a,b:longint;
c:ab;
end;
var
n,m,tot,sum:longint;
p:array[0..30000]of ab;
v:array[0..30000]of boolean;
f,f1:array[0..30000,0..200]of longint;
d:array[0..30000]of longint;
procedure put(x,y:longint);
var
i:ab;
begin
new(i);
i^.a:=y;
i^.c:=p[x];
p[x]:=i;
end;
procedure fq(x,y,z:longint);
var
i,j:longint;
begin
f[y,0]:=x;
f1[y,0]:=z;
i:=x; j:=1;
while f[i,j-1]>0 do
begin
f[y,j]:=f[i,j-1];
f1[y,j]:=f1[y,j-1]+f1[i,j-1];
i:=f[i,j-1];
inc(j);
end;
end;
procedure find(x,y:longint);
var
i:ab;
begin
v[x]:=true;
d[x]:=y;
i:=p[x];
while i<>nil do
begin
if v[i^.a]=false then
begin
fq(x,i^.a,1);
find(i^.a,y+1);
end;
i:=i^.c;
end;
end;
function fa(x,y:longint):longint;
var
i,j:longint;
begin
if d[x]<d[y] then
begin
i:=x;x:=y;y:=i;
end;
i:=d[x]-d[y];
j:=0;
while i>0 do
begin
if i mod 2=1 then
begin
sum:=f1[x,j]+sum;
x:=f[x,j];
end;
i:=i div 2;
j:=j+1;
end;
if x=y then exit(sum);
j:=0;
while f[x,0]<>f[y,0] do
begin
while f[x,j]=f[y,j] do dec(j);
sum:=sum+f1[x,j];
x:=f[x,j];
sum:=sum+f1[y,j];
y:=f[y,j];
j:=j+1;
end;
sum:=sum+f1[x,0];
sum:=sum+f1[y,0];
exit(sum);
end;
var
i,s,t:longint;
begin
readln(n);
for i:=1 to n-1 do
begin
readln(s,t);
put(s,t);
put(t,s);
end;
find(1,1);
readln(m);
readln(s);
for i:=2 to m do
begin
sum:=0;
readln(t);
tot:=tot+fa(s,t);
s:=t;
end;
writeln(tot);
end.