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倍
蒟蒻不会