LCA模板
树链剖分LCA
O(n)-O(logn)
#include<iostream>
#include<cstdio>
const int N=500005;
int n,m,S,ecnt,head[N],tim;
struct Edge{int to,nxt;}e[N<<1];
void add(int bg,int ed){e[++ecnt].nxt=head[bg];e[ecnt].to=ed;head[bg]=ecnt;}
int fa[N],dfn1[N],top[N],dfn2[N],son[N],dep[N],siz[N],rnk[N];
void dfs1(int x){
siz[x]=1;
dep[x]=dep[fa[x]]+1;
for(int i=head[x],v;i;i=e[i].nxt){v=e[i].to;
if(v==fa[x]) continue;
fa[v]=x;
dfs1(v);
siz[x]+=siz[v];
if(siz[son[x]]<siz[v]) son[x]=v;
}
}
void dfs2(int x,int qtop){
top[x]=qtop;
dfn1[x]=++tim;
rnk[tim]=x;
if(son[x]) dfs2(son[x],qtop);
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[x]||v==son[x])continue;
dfs2(v,v);
}
dfn2[x]=tim;
}
int main(){
scanf("%d%d%d",&n,&m,&S);
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),add(u,v),add(v,u);
dfs1(S);dfs2(S,S);
for(int i=1,x,y;i<=m;i++){
scanf("%d%d",&x,&y);
while(top[x]!=top[y]){
if(dep[top[x]]>=dep[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
}
printf("%d\n",dep[x]<dep[y]?x:y);
}
}
tarjan flag++;
倍增 O(nlogn)-O(logn)
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1000005;
int n,q,nxt[N],to[N],fa[N][25],ecnt,head[N],dep[N],S;
inline void add(int bg,int ed) {nxt[++ecnt]=head[bg];to[ecnt]=ed;head[bg]=ecnt;}
void dfs(int x,int f) {
fa[x][0]=f;dep[x]=dep[f]+1;
for(int i=1;i<=24;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=head[x];i;i=nxt[i]) {
if(to[i]==f) continue;
dfs(to[i],x);
}
}
int lca(int x,int y) {
if(x==y) return x;
if(dep[x]<dep[y])swap(x,y);
for(int i=24;~i;i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
//cout<<dep[x]<<' '<<dep[y]<<endl;
if(x==y) return x;
for(int i=24;~i;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main() {
scanf("%d%d%d",&n,&q,&S);
for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(S,0);
int x,y;
while(q--) {
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}
RMQ+欧拉序 O(logn)-O(1)
#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
const int N=1000005;
int n,q,nxt[N],to[N],val[N],Min[25][N],ecnt,head[N],tim,dep[N],rnk[N],dfn[N],S,node[25][N];
inline void add(int bg,int ed) {nxt[++ecnt]=head[bg];to[ecnt]=ed;head[bg]=ecnt;}
void dfs(int x,int f) {
dep[x]=dep[f]+1;dfn[x]=++tim;Min[0][tim]=dep[x];node[0][tim]=x;
for(int i=head[x];i;i=nxt[i]) {
if(to[i]==f) continue;
dfs(to[i],x);
Min[0][++tim]=dep[x];node[0][tim]=x;
}
}
void ask(int x,int y) {
if(x>y) swap(x,y);
int k=log2(y-x+1);
if(Min[k][x]<Min[k][y-(1<<k)+1]) printf("%d\n",node[k][x]);
else printf("%d\n",node[k][y-(1<<k)+1]);
return ;
}
int main() {
scanf("%d%d%d",&n,&q,&S);
for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(S,0);
for(int i=1;(1<<i)<=tim;i++) {
for(int j=1;j+(1<<i)-1<=tim;j++) {
if(Min[i-1][j]<Min[i-1][j+(1<<i-1)]) {
Min[i][j]=Min[i-1][j];
node[i][j]=node[i-1][j];
}
else {
Min[i][j]=Min[i-1][j+(1<<i-1)];
node[i][j]=node[i-1][j+(1<<i-1)];
}
}
}
int x,y;
while(q--) {
scanf("%d%d",&x,&y);
ask(dfn[x],dfn[y]);
}
}
我是咸鱼。转载博客请征得博主同意Orz