標籤:
【問題描述】
某首都城市的商人要經常到各城鎮去做生意,他們按自己的路線去做,目的是為了更好的節約時間。
假設有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 }
聲明:本文章系博主原創,未經允許請勿轉載。
[CODEVS 1036]商務旅行