商务旅行

来源:互联网 发布:爱国 知乎 编辑:程序博客网 时间:2024/06/06 12:25

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.
0 0