[CODEVS 1036]商务旅行
【问题描述】
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
【输入】
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。
下面N-1行,每行由两个整数a 和b (1<=a, b<=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 }
声明:本文章系博主原创,未经允许请勿转载。