题目:洛谷P3379
朴素版
//朴素lca
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+1000;
int m,n,s,d[N],fa[N];
vector<int>g[N];
void dfs(int u){
for(int i=0;i<(int)g[u].size();i++){
int x=g[u][i];
if(x==fa[u])continue;
fa[x]=u;
d[x]=d[u]+1;
dfs(x);
}
}
int qru(int a,int b){
if(d[a]<d[b])swap(a,b);
while(d[a]!=d[b])a=fa[a];
while(a!=b){
a=fa[a];
b=fa[b];
}
return a;
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs(s);
while(m--){
int a,b;
scanf("%d%d",&a,&b);
int x=qru(a,b);
printf("%d\n",x);
}
}
倍增版
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+1000;
int n,m,k,s,d[N],f[N][64];//f[i][k],代表i的2^k级祖先
vector<int>g[N];
void add(int a,int b){
g[a].push_back(b);
g[b].push_back(a);
}
//初始化每个节点的深度
void dfs(int x,int fa){
for(int i=0;i<(int)g[x].size();i++){
int v=g[x][i];
if(v==fa)continue;//处理自环
d[v]=d[x]+1;
f[v][0]=x;//点v的父亲为x
dfs(v,x);
}
}
//初始化f[i][k],找出其所有的关系
void init(){
for(int j=1;j<=k;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
int qlca(int a,int b){
if(d[a]<d[b])swap(a,b);//保证a的深度大
for(int i=k;i>=0;i--)
if(d[f[a][i]]>=d[b])a=f[a][i];//将a提升至和b一样的深度,按2^i提升
if(a==b)return a;
for(int i=k;i>=0;i--)//两个点一起提升2^i
if(f[a][i]!=f[b][i]){
a=f[a][i];
b=f[b][i];
}
return f[a][0];
}
int main(){
cin>>n>>m>>s;
k=log2(n);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
}
d[s]=1;//根节点的深度为1
dfs(s,0);//s为当前点,0为其父亲
init();
while(m--){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",qlca(a,b));
}
}