標籤:
題目描述
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
/* 倍增 LCA */#include<cstdio>#include<iostream>#include<vector>#define M 30010#define S 20using namespace std;int deep[M],fa[M][S+5],n,m;vector<int> grap[M];void dfs(int now,int from,int c){ fa[now][0]=from; deep[now]=c; for(int i=0;i<grap[now].size();i++) if(from!=grap[now][i]) dfs(grap[now][i],now,c+1);}void get_fa(){ for(int j=1;j<=S;j++) for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1];}int get_same(int a,int t){ for(int i=0;i<=S;i++) if(t&(1<<i)) a=fa[a][i]; return a;}int LCA(int a,int b){ if(deep[a]<deep[b])swap(a,b); a=get_same(a,deep[a]-deep[b]); if(a==b)return a; for(int i=S;i>=0;i--) if(fa[a][i]!=fa[b][i]) { a=fa[a][i]; b=fa[b][i]; } return fa[a][0];}int main(){ scanf("%d",&n); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); grap[x].push_back(y); grap[y].push_back(x); } dfs(1,1,0); get_fa(); int p1,p2,ans=0; scanf("%d%d",&m,&p1); for(int i=1;i<m;i++) { scanf("%d",&p2); int zu=LCA(p1,p2); ans+=(deep[p1]+deep[p2]-2*deep[zu]); p1=p2; } printf("%d",ans); return 0;}
View Code
商務旅行(codevs 1036)