codevs 1036 商务旅行
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 钻石 Diamond
题目描述 Description
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入描述 Input Description
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
输出描述 Output Description
在输出文件中输出该商人旅行的最短时间。
样例输入 Sample Input
5
1 2
1 5
3 5
4 5
4
1
3
2
5
样例输出 Sample Output
7
1 #define N 60100 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 #include<cstring> 6 #define C 20 7 typedef long long ll; 8 int ance[N>>1][C],dis[N>>1],n,a,b,m; 9 ll sum=0; 10 struct Edge{ 11 int v,last; 12 }edge[N<<1]; 13 int deep[N>>1],head[N>>1],t=0; 14 void add_edge(int u,int v) 15 { 16 ++t; 17 edge[t].v=v; 18 edge[t].last=head[u]; 19 head[u]=t; 20 } 21 void input() 22 { 23 scanf("%d",&n); 24 for(int i=1;i<n;++i) 25 { 26 scanf("%d%d",&a,&b); 27 add_edge(a,b); 28 add_edge(b,a);/*注意树上建边必须是双向的*/ 29 } 30 } 31 void dfs(int k) 32 { 33 for(int l=head[k];l;l=edge[l].last) 34 { 35 if(!deep[edge[l].v]) 36 { 37 dis[edge[l].v]=dis[k]+1; 38 ance[edge[l].v][0]=k; 39 deep[edge[l].v]=deep[k]+1; 40 dfs(edge[l].v); 41 } 42 } 43 } 44 void chuli_ance() 45 { 46 for(int i=1;(1<<i)<=n;++i) 47 for(int j=1;j<=n;++j) 48 ance[j][i]=ance[ance[j][i-1]][i-1]; 49 } 50 int lca(int a,int b) 51 { 52 int i,j; 53 if(deep[a]<deep[b]) swap(a,b); 54 for(i=0;(1<<i)<=deep[a];++i); 55 i--; 56 for(j=i;j>=0;--j) 57 if(deep[a]-(1<<j)>=deep[b]) 58 a=ance[a][j]; 59 if(a==b) return a; 60 for(j=i;j>=0;--j) 61 { 62 if(ance[a][j]!=-1&&ance[a][j]!=ance[b][j]) 63 { 64 a=ance[a][j]; 65 b=ance[b][j]; 66 } 67 } 68 return ance[a][0]; 69 } 70 int main() 71 { 72 input(); 73 deep[1]=1; 74 dis[1]=0; 75 memset(ance,-1,sizeof(ance)); 76 dfs(1); 77 chuli_ance(); 78 scanf("%d",&m); 79 scanf("%d",&a); 80 int sta=a; 81 for(int i=2;i<=m;++i) 82 { 83 scanf("%d",&b); 84 int zuxian=lca(a,b); 85 sum+=(dis[a]+dis[b]-2*dis[zuxian]); 86 a=b; 87 } 88 sum+=dis[sta]; 89 cout<<sum<<endl; 90 return 0; 91 }