标签:
某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间。
假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意两个城镇之间如果有直连道路,在他们之间行驶需要花费单位时间。该国公路网络发达,从首都出发能到达任意一个城镇,并且公路网络不会存在环。
你的任务是帮助该商人计算一下他的最短旅行时间。
输入文件中的第一行有一个整数N,1<=n<=30 000,为城镇的数目。下面N-1行,每行由两个整数a 和b (1<=a, b<=n; a<>b)组成,表示城镇a和城镇b有公路连接。在第N+1行为一个整数M,下面的M行,每行有该商人需要顺次经过的各城镇编号。
在输出文件中输出该商人旅行的最短时间。
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 }
标签:
原文地址:http://www.cnblogs.com/gzhonghui/p/5757799.html