標籤:
題目描述
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
在輸出檔案中輸出該商人旅行的最短時間。
LCA問題,可以轉化為RMQ問題
dep[]表示節點在樹中的深度
F是歐拉序列,B是歐拉序列節點對應的深度
pos[]表示節點第一次在歐拉序列中出現的位置
LCA(T,u,v)=F[RMQ(B,pos[u],pos[v])]
這裡RMQ要返回座標,而不是具體值,但本題不需要,本題只要得到LCA的深度即可,直接讓RMQ返回具體值即可,所求深度就是這個傳回值
最小值也可以用線段樹維護
1 #include<iostream> 2 #include<cstring> 3 using namespace std; 4 const int maxn=30001; 5 struct node{ 6 int l,r,mmin; 7 }tree[8*maxn]; 8 struct edge{ 9 int go,next;10 }e[2*maxn];11 int dep[maxn],N,end[maxn],ecount=0,count=0,F[2*maxn],B[2*maxn],M,pos[maxn],v[maxn];12 void add(int a,int b){13 e[++ecount].go=b;14 e[ecount].next=end[a];15 end[a]=ecount;16 }17 void buildTree(int f,int x,int d){18 int go;19 dep[x]=d;20 F[++count]=x;21 B[count]=d;22 if(!v[x]){23 pos[x]=count;v[x]=1;24 }25 for(int i=end[x];i;i=e[i].next){26 go=e[i].go;27 if(go!=f){28 buildTree(x,go,d+1);29 F[++count]=x;30 B[count]=d;31 }32 } 33 }34 void init()35 {36 memset(end,0,sizeof(end));37 memset(v,0,sizeof(v));38 }39 void build(int o,int l,int r){40 if(l==r){41 tree[o].l=tree[o].r=l;42 tree[o].mmin=B[l];43 return;44 }45 int m=(l+r)/2;46 build(2*o,l,m);build(2*o+1,m+1,r);47 tree[o].l=l,tree[o].r=r;48 tree[o].mmin=min(tree[o*2].mmin,tree[o*2+1].mmin);49 }50 int query(int o,int l,int r){51 if(l<=tree[o].l&&tree[o].r<=r) return tree[o].mmin;52 int m=(tree[o].l+tree[o].r)/2;53 int ans=1<<30;54 if(l<=m) ans=min(ans,query(2*o,l,r));55 if(m<r) ans=min(ans,query(2*o+1,l,r));56 return ans;57 }58 int main()59 {60 cin>>N;61 init();62 int x,y;63 for(int i=2;i<=N;i++){64 cin>>x>>y;65 add(x,y),add(y,x);66 }67 buildTree(-1,1,0); 68 build(1,1,count);69 //for(int i=1;i<=count;i++) cout<<i<<"F:"<<F[i]<<endl;70 cin>>M;71 int last,ans=0,to;72 cin>>last;73 for(int i=1;i<M;i++){74 cin>>to;75 ans+=dep[last]+dep[to]-2*B[query(1,min(pos[last],pos[to]),max(pos[last],pos[to]))];76 last=to;77 } 78 cout<<ans;79 return 0;80 }
CODEVS 1036 商務旅行