#include<algorithm>#include<cstring>#include<iostream>usingnamespacestd;classEdge{public:inttoVertex,fromVertex;intnext;intLCA;Edge():toVertex(-1),fromVertex(-1),next(-1),LCA(-1){};Edge(intu,intv,intn):fromVertex(u),toVertex(v),next(n),LCA(-1){};};constexprintMAX=100;inthead[MAX],queryHead[MAX];Edgeedge[MAX],queryEdge[MAX];// ancestor[r]:以 r 为根的集合中深度最小的结点intparent[MAX],setSize[MAX],ancestor[MAX],visited[MAX];intvertexCount,queryCount;intfind(intx){if(parent[x]==x){returnx;}else{returnparent[x]=find(parent[x]);}}// 按集合大小合并 x 与 y 所在的集合,返回合并后集合的根intunite(intx,inty){x=find(x);y=find(y);if(setSize[x]<setSize[y])swap(x,y);parent[y]=x;setSize[x]+=setSize[y];returnx;}voidtarjan(intu){parent[u]=u;setSize[u]=1;ancestor[u]=u;visited[u]=1;for(inti=head[u];i!=-1;i=edge[i].next){Edge&e=edge[i];if(!visited[e.toVertex]){tarjan(e.toVertex);// 子树并入 u 所在的集合,合并后集合中深度最小的结点仍是 uancestor[unite(u,e.toVertex)]=u;}}for(inti=queryHead[u];i!=-1;i=queryEdge[i].next){Edge&e=queryEdge[i];if(visited[e.toVertex]){queryEdge[i^1].LCA=e.LCA=ancestor[find(e.toVertex)];}}}intmain(){memset(head,0xff,sizeof(head));memset(queryHead,0xff,sizeof(queryHead));cin>>vertexCount>>queryCount;intcount=0;for(inti=0;i<vertexCount-1;i++){intstart=0,end=0;cin>>start>>end;edge[count]=Edge(start,end,head[start]);head[start]=count;count++;edge[count]=Edge(end,start,head[end]);head[end]=count;count++;}count=0;for(inti=0;i<queryCount;i++){intstart=0,end=0;cin>>start>>end;queryEdge[count]=Edge(start,end,queryHead[start]);queryHead[start]=count;count++;queryEdge[count]=Edge(end,start,queryHead[end]);queryHead[end]=count;count++;}tarjan(1);for(inti=0;i<queryCount;i++){Edge&e=queryEdge[i*2];cout<<"("<<e.fromVertex<<","<<e.toVertex<<") "<<e.LCA<<endl;}return0;}
classLcaSolver{std::array<std::vector<int>,30>mi;std::vector<int>dfn,log;autoget(intu,intv)const{returndfn[u]<dfn[v]?u:v;}public:// Initialize.// n - tree size; fa - the id of parent node, 0-indexed, 0 is the root.LcaSolver(intn,conststd::vector<int>&fa):dfn(n),log(n+1){// Build the tree.std::vector<std::vector<int>>gr(n);for(inti=1;i<n;++i)gr[fa[i]].push_back(i);// DFS.autoid=0;autodfs=[&](auto&&dfs,intcr)->void{dfn[cr]=id++;for(intnt:gr[cr])dfs(dfs,nt);};dfs(dfs,0);// Build ST table.for(inti=2;i<=n;++i)log[i]=log[i>>1]+1;mi[0].assign(n,0);for(inti=0;i<n;++i)mi[0][dfn[i]]=fa[i];for(intk=1;k<=log[n];++k){mi[k].assign(n-(1<<k)+1,0);for(inti=0;i+(1<<k)<=n;++i)mi[k][i]=get(mi[k-1][i],mi[k-1][i+(1<<(k-1))]);}}// Find the LCA.intlca(intu,intv)const{if(u==v)returnu;u=dfn[u],v=dfn[v];if(u>v)std::swap(u,v);autok=log[v-u];returnget(mi[k][u+1],mi[k][v-(1<<k)+1]);}};
#include<algorithm>#include<cmath>#include<iostream>usingnamespacestd;constexprintN=5e5+5;structPlusMinusOneRMQ{// RMQ// Copyright (C) 2018 Skqliao. All rights served.constexprstaticintM=9;intblocklen,block,Minv[N],F[N/M*2+5][M<<1],T[N],f[1<<M][M][M],S[N];voidinit(intn){// 初始化blocklen=std::max(1,(int)(log(n*1.0)/log(2.0))/2);block=n/blocklen+(n%blocklen>0);inttotal=1<<(blocklen-1);for(inti=0;i<total;i++){for(intl=0;l<blocklen;l++){f[i][l][l]=l;intnow=0,minv=0;for(intr=l+1;r<blocklen;r++){f[i][l][r]=f[i][l][r-1];if((1<<(r-1))&i){now++;}else{now--;if(now<minv){minv=now;f[i][l][r]=r;}}}}}T[1]=0;for(inti=2;i<N;i++){T[i]=T[i-1];if(!(i&(i-1))){T[i]++;}}}voidinitmin(inta[],intn){for(inti=0;i<n;i++){if(i%blocklen==0){Minv[i/blocklen]=i;S[i/blocklen]=0;}else{if(a[i]<a[Minv[i/blocklen]]){Minv[i/blocklen]=i;}if(a[i]>a[i-1]){S[i/blocklen]|=1<<(i%blocklen-1);}}}for(inti=0;i<block;i++){F[i][0]=Minv[i];}for(intj=1;(1<<j)<=block;j++){for(inti=0;i+(1<<j)-1<block;i++){intb1=F[i][j-1],b2=F[i+(1<<(j-1))][j-1];F[i][j]=a[b1]<a[b2]?b1:b2;}}}intquerymin(inta[],intL,intR){intidl=L/blocklen,idr=R/blocklen;if(idl==idr)returnidl*blocklen+f[S[idl]][L%blocklen][R%blocklen];else{intb1=idl*blocklen+f[S[idl]][L%blocklen][blocklen-1];intb2=idr*blocklen+f[S[idr]][0][R%blocklen];intbuf=a[b1]<a[b2]?b1:b2;intc=T[idr-idl-1];if(idr-idl-1){intb1=F[idl+1][c];intb2=F[idr-1-(1<<c)+1][c];intb=a[b1]<a[b2]?b1:b2;returna[buf]<a[b]?buf:b;}returnbuf;}}}rmq;intn,m,s;structEdge{intv,nxt;}e[N*2];inttot,head[N];voidinit(intn){tot=0;fill(head,head+n+1,0);}voidaddedge(intu,intv){// 加边++tot;e[tot]=Edge{v,head[u]};head[u]=tot;++tot;e[tot]=Edge{u,head[v]};head[v]=tot;}intdfs_clock,dfn[N*2],dep[N*2],st[N];voiddfs(intu,intfa,intd){st[u]=dfs_clock;dfn[dfs_clock]=u;dep[dfs_clock]=d;++dfs_clock;intv;for(inti=head[u];i;i=e[i].nxt){v=e[i].v;if(v==fa)continue;dfs(v,u,d+1);dfn[dfs_clock]=u;dep[dfs_clock]=d;++dfs_clock;}}voidbuild_lca(){// like initrmq.init(dfs_clock);rmq.initmin(dep,dfs_clock);}intLCA(intu,intv){// 求解LCA,看题解用RMQ的方法intl=st[u],r=st[v];if(l>r)swap(l,r);returndfn[rmq.querymin(dep,l,r)];}intmain(){cin.tie(nullptr)->sync_with_stdio(false);cin>>n>>m>>s;init(n);intu,v;for(inti=1;i<=n-1;++i){cin>>u>>v;addedge(u,v);}dfs_clock=0;dfs(s,s,0);build_lca();for(inti=1;i<=m;++i){cin>>u>>v;cout<<LCA(u,v)<<'\n';}return0;}