這段故事仍然不屬於勇者。
——————————————
題目描述 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之後就能AC的題。
然後路由器花了一整週的時間debug。
另外多虧了互聯網的神奇功能。
看了大家的題解之後驚醒發現一個問題。
鏈式前向星一定要開二倍大!(很容易明白這個問題……然而debug……)
好的廢話不多說,倍增LCA暴力解決就ok。
這題只要有思想就能AC啦!小細節在代碼裏給註釋。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
int deep[30010]={0};//節點深度
int anc[30010][16]={0};
int m,n,cnt=0;
int cnt1=0,head[60020]={0}; //二倍大!
struct{
int to;
int next;
}edge[60020];//二倍大!
void add(int u,int v){//鏈前,u起點v終點
cnt1++;
edge[cnt1].to=v;
edge[cnt1].next=head[u];
head[u]=cnt1;
}
void dfs(int i){//搜索層數與每個節點的父親使用
for(int j=head[i];j!=0;j=edge[j].next){
int k=edge[j].to;
if(anc[k][0]==0){
anc[k][0]=i;
deep[k]=deep[i]+1;
dfs(k);
}
}
return;
}
int suan(int i,int j){//求i與j的LCA
while(deep[i]!=deep[j]){//不同層化同層
int dd;
dd=abs(deep[i]-deep[j]);
int l,k;
for(l=15;;l--){
if(pow(2,l)<=dd){
break;
}
}
if(deep[i]>deep[j]){
i=anc[i][l];
}else{
j=anc[j][l];
}
}
if(i==j)return i;//這裏要注意!!WA過一次
while(anc[i][0]!=anc[j][0]){//倍增找LCA
int k;
for(k=14;k>=0;k--){
if(anc[i][k]==anc[j][k])continue;
break;
}
i=anc[i][k];j=anc[j][k];
}
return anc[i][0];//LCA
}
int main(){
scanf("%d",&n);
anc[1][0]=0;deep[1]=deep[0]=1;//根節點指向0節點,0節點deep記爲1
for(int i=1;i<=n-1;i++){
int a,b;
scanf("%d %d",&a,&b);//正反都要存
add(a,b);
add(b,a);
}
dfs(1);
for(int j=1;j<=14;j++){
for(int i=1;i<=n;i++){
anc[i][j]=anc[anc[i][j-1]][j-1];//2^n=2*2^(n-1)=2^(n-1)+2^(n-1)
}
}
scanf("%d",&m);
int start=1,end;
for(int i=1;i<=m;i++){
scanf("%d",&end);
cnt+=deep[start]+deep[end]-2*deep[suan(start,end)];
start=end;
}
printf("%d",cnt);
return 0;
}