\(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; }
来源:https://www.cnblogs.com/lhm-/p/12229472.html