LCA
\(LCA\),即最近公共祖先,是指在有根树中,找出某两个结点\(u\)和\(v\)最近的公共祖先
倍增法求\(LCA\),核心本质是让两个结点每次向上走2的幂次步
先处理出倍增数组\(fa\),\(fa[i][j]\)为从结点\(i\)向上走\(2^{j}\)步后能走到的结点
再将两个点移到同一深度
最后开始倍增来跳深度,应用了二进制拆分思想
时间复杂度为\(O(n\ log\ n)\)
\(code\):
void dfs(int x,int fath)
{
de[x]=de[fath]+1;//求深度
fa[x][0]=fath;
for(int i=1;(1<<i)<=de[x];++i)
fa[x][i]=fa[fa[x][i-1]][i-1];//初始化倍增
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(y==fath) continue;
dfs(y,x);
}
return;
}
int lca(int x,int y)
{
if(de[x]<de[y]) swap(x,y);
for(int i=20;~i;--i)
if(de[fa[x][i]]>=de[y])
x=fa[x][i];
if(x==y) return x;
for(int i=20;~i;--i)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];
}
也可以用树链剖分求\(LCA\)
\(code\):
int lca(int x,int y)
{
while(top[x]!=top[y])
{
if(de[top[x]]<de[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(dfn[x]>dfn[y]) swap(x,y);
return x;
}