概念
一棵有根树,求两个点的最近公共祖先。
方法
1. 倍增法:\(O(n)-O(\log n)\)
int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y]) x=fa[x][__lg(dep[x]-dep[y])-1];
if(x==y) return x;
for(int k=__lg(dep[x])-1; ~k; k--)
if(fa[x][k]!=fa[y][k]) x=fa[x][k],y=fa[y][k];
return fa[x][0];
}
2. dfs 序求 lca:\(O(n\log n)-O(1)\)
int get(int x,int y) {return dfn[x]<dfn[y]?x:y;}
void dfs(int x,int fa) {
st[dfn[x]=++cnt][0]=fa;
st[1][1]=fa;
for(auto y:e[x]) if(y!=fa) dfs(y,x);
}
void build_st() {
int k=__lg(n);
for(int i=1; i<=k; i++)
for(int j=1; j+(1<<i)-1<=n; j++)
st[j][i]=get(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
int lca(int x,int y) {
if(x==y) return x;
if((x=dfn[x])>(y=dfn[y])) swap(x,y);
int k=__lg(y-x++);
return get(st[x][k],st[y-(1<<k)+1][k]);
}
3. 树剖求 lca:\(O(n)-O(\log n)\)
int lca(int x,int y) {
while(top[x]^top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y]?x:y;
}
标签:__,dep,return,fa,祖先,lca,笔记,int,公共
From: https://www.cnblogs.com/lgh-blog/p/18133844