今天是2017/7/10,DCDCBigBig的第二十三篇博文
树上倍增(LCA)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct edge{
int v,next;
}a[100001];
int n,q,u,v,rt,tot=0,head[100001],fa[100001][31],dep[100001];
bool vis[100001];
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void cal_dep(int u){
vis[u]=true;
for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
int v=a[tmp].v;
if(!vis[v]){
dep[v]=dep[u]+1;
cal_dep(v);
}
}
}
void cal(){
for(int j=1;j<=30;j++){
for(int i=1;i<=n;i++){
fa[i][j]=fa[fa[i][j-1]][j-1];
}
}
}
int lca(int x,int y){
if(dep[x]<dep[y]){
swap(x,y);
}
int s=dep[x]-dep[y];
for(int i=0;i<30;i++){
if((1<<i)&s)x=fa[x][i];
}
if(x==y)return x;
for(int i=29;i>=0;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
int main(){
memset(head,-1,sizeof(head));
memset(fa,0,sizeof(fa));
memset(dep,0,sizeof(dep));
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&q);
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
fa[v][0]=u;
}
dep[1]=1;
cal_dep(1);
cal();
for(int i=1;i<=q;i++){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return 0;
}
笑