商务旅行

题目描述 Description

某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。

假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。

你的任务是帮助该商人计算一下他的最短旅行时间。

输入描述 Input Description

输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=ab<=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

思路:裸的LCA
代码实现:
 1 #include<cstdio>
 2 const int maxn=30010;
 3 int n,m,ans;
 4 int a,b,c;
 5 int h[maxn],hs=1;
 6 struct edge{int s,n;}e[maxn<<1];
 7 void add(int q,int z){e[++hs]=(edge){z,h[q]},h[q]=hs;}
 8 int f[maxn],d[maxn];
 9 void dfs(int k,int fa,int de){
10     f[k]=fa,d[k]=de;
11     for(int i=h[k];i;i=e[i].n)
12     if(e[i].s!=fa) dfs(e[i].s,k,de+1);
13 }
14 int main(){
15     scanf("%d",&n);
16     for(int i=1;i<n;i++){
17         scanf("%d%d",&a,&b);
18         add(a,b),add(b,a);
19     }
20     dfs(1,0,1);
21     scanf("%d%d",&m,&a);
22     for(int i=1;i<m;i++){
23         scanf("%d",&b),c=b;
24         while(a!=b){
25             ans++;
26             if(d[a]>d[b]) a=f[a];
27             else b=f[b];
28         }
29         a=c;
30     }
31     printf("%d\n",ans);
32     return 0;
33 }

本来想写树链剖分练练手,结果莫名R,然后顺手写了个LCA(裸的),竟然没T跑的还挺快。

题目来源:CODE[VS]

posted @ 2017-03-24 19:55  J_william  阅读(237)  评论(0编辑  收藏  举报