LCA
最近公共祖先
倍增
在线算法
时间复杂度 \(O((n+q)\log\ n)\)
空间复杂度 \(O(n \log n)\)
fa[x][k]
表示 \(x\) 的 \(2^k\) 祖先
dep[x]
表示 \(x\) 的深度
log[x]
表示 \(log_2\ x\)
void pre_lca(int now,int father) //预处理LCA
{
dep[now]=dep[father]+1;
fa[now][0]=father;
for(int i=1;(1<<i)<=dep[now];i++)
fa[now][i]=fa[fa[now][i-1]][i-1];
for(int i=head[now];i;i=edge[i].next)
if(edge[i]!=father)
pre_lca(edge[i].to,now);
}
void pre_log() //预处理log_2 方便查询
{
log[0]=-1;
for(int i=1;i<=MAX;i++)
log[i]=log[i>>1]+1;
}
int lca(int x,int y) //求x y两点的LCA
{
if(dep[x]<dep[y]) //令x深度比y大
swap(x,y);
while(dep[x]>dep[y]) //令x向上跳 直到和y同一高度
x=fa[x][log[dep[x]-dep[y]]];
if(x==y) //若x跳到了y上 说明y是x的父结点
return x;
for(int i=log[dep[x]];i>=0;i--)
if(fa[x][i]!=fa[y][i]) //若x y的父结点不同 就可以向上跳
{
x=fa[x][i];
y=fa[y][i];
}
return f[x][0]; //此时x y的父结点就是LCA
}
tarjan
@HRLYB 最喜欢的方法 码量小 据说比倍增快4倍
蒟蒻不会