倍增求LCA(240822)
介绍:LCA为最近公共祖先,表示离两个点最近的公共祖先
解法:从两个点中的一个往上跳:
第一次跳$2^0$
第二次跳$2^1$
第三次跳$2^2$......
这样就可以$O(logN)$解决问题
代码实现:
先求每个点深度,并记录父亲
void dfs1(ll x,ll sc){
faa[x]=sc;//深度
vis[x]=1;
for(int i=head[x];i;i=es[i].nxt){
ll v=es[i].v;
if(!vis[v]){
fa[v][0]=x;
dfs1(v,sc+1);
}
}
}
再算出第\(2^i\)个父亲是谁
for(int i=1;i<=17;i++){
for(int j=1;j<=n;j++){
fa[j][i]=fa[fa[j][i-1]][i-1];
//这里要理解,假设i=2,那求出的就是j点的第2^(i-1)个父亲的第2^(i-1)个父亲
//也就是4,满足2^2=4
}
}
最后再往上跳
ll lca(ll x,ll y){
if(faa[x]<faa[y]){//y深度要小
swap(x,y);
}
for(int i=17;i>=0;i--){//把x往上跳,尽量跳到与y同一层
if(faa[fa[x][i]]>=faa[y]){
x=fa[x][i];
}
}
if(x==y){
return x;
}
for(int i=17;i>=0;i--){
if(fa[x][i]!=fa[y][i]){//不可以等于,要跳到LCA的下面一层
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][0];//上面一层即为答案
}
可以自由转载

浙公网安备 33010602011771号