[CODEVS 1036]商务旅行

【问题描述】

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

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

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

【输入】

  输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。

  下面N-1行,每行由两个整数a 和b (1<=ab<=n; a<>b)组成,表示城镇a和城镇b有公路连接。

  在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。

【输出】

  在输出文件中输出该商人旅行的最短时间。

【算法分析】

  直接使用Tarjan离线LCA算法可以通过所有数据。

【程序代码】

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 int g[30010][510],dis[30010],num[30010],point[30010],n,m,ans=0;
 5 int fa[30010],que[30010][3];
 6 bool bo[30010];
 7 void buildtree(int u){
 8     for (int i=1;i<=num[u];i++)
 9     if (!bo[g[u][i]]){
10         bo[g[u][i]]=true;
11         dis[g[u][i]]=dis[u]+1;
12         buildtree(g[u][i]);
13     }
14 }
15 int find(int u){
16     return fa[u]==u?u:fa[u]=find(fa[u]);
17 }
18 void tarjan(int u){
19     bo[u]=true;
20     for (int i=1;i<=que[u][0];i++)
21     if (bo[que[u][i]]) ans+=dis[u]+dis[que[u][i]]-2*dis[find(que[u][i])];
22     for (int i=1;i<=num[u];i++)
23     if (!bo[g[u][i]]){
24         tarjan(g[u][i]);
25         fa[g[u][i]]=u;
26     }
27 }
28 int main(){
29     memset(g,0,sizeof(g));
30     memset(num,0,sizeof(num));
31     memset(dis,0,sizeof(dis));
32     memset(point,0,sizeof(point));
33     memset(bo,0,sizeof(bo));
34     memset(que,0,sizeof(que));
35     scanf("%d",&n);
36     for (int i=1;i<=n;i++) fa[i]=i;
37     for (int i=1;i<n;i++){
38         int x,y;
39         scanf("%d%d",&x,&y);
40         g[x][++num[x]]=y;
41         g[y][++num[y]]=x;
42     }
43     bo[1]=true; dis[1]=0;
44     buildtree(1);
45     scanf("%d",&m);
46     memset(bo,0,sizeof(bo));
47     for (int i=1;i<=m;i++) {
48         scanf("%d",&point[i]);
49         if (i==1&&point[i]==1) continue;
50         else if (i==1&&point[i]!=1){
51             que[point[i]][++que[point[i]][0]]=1;
52             que[1][++que[1][0]]=point[i];
53         }
54         else{
55             que[point[i]][++que[point[i]][0]]=point[i-1];
56             que[point[i-1]][++que[point[i-1]][0]]=point[i];
57         }
58     }
59     tarjan(1);
60     printf("%d",ans);
61     return 0;
62 }

声明:本文章系博主原创,未经允许请勿转载。

posted on 2016-04-09 10:09  Double680  阅读(223)  评论(0编辑  收藏  举报

导航