倍增算法

1.求LCA

首先求出每个节点的深度, 如果我们要求u, v 的LCA

首先找到 u 的一个和 v 在同一深度的祖先 u’ , 则 LCA(u, v) = LCA(u’ , v)

若 u’ = v , 说明 u’ 正好就是LCA(u, v) , 否则:

  • u’, v 两个点同时向上跳 2j 步,
    1. 若指向同一个点, 说明他们距离LCA小于等于 2j , 此时我们减少上跳幅度
    2. 若指向不同的点, 重复 1, 2, 直到 j = 0, 再跳一步, 正好到达 LCA

算法步骤

  1. dfs预处理, f[i][j] 表示 i 的 2j 级祖先
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;//当前节点深度为父节点深度 +1
    for(int i=1;(1<<i)<=dep[u];i++)
        f[u][i]=f[f[u][i-1]][i-1];//根据u的深度,预处理其2^i祖先 
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa)continue;
        f[v][0]=u;//v的父亲节点是u 
        dfs(v,u);
    }
}

2.上调至同一深度

u, v不在同一个深度时,我们要用倍增思想把深度大的节点u调到和v在同一个深度。

int len=dep[u]-dep[v],k=0;
while(len){//对k进行二进制分解
    if(len & 1) u=f[u][k];//如果当前位为1
    ++k;len>>=1;//k记录处理到 len 的第几个二进制位
  1. 代码全貌
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+5,maxe=1e5+5;
int n, len, head[maxn], dep[maxn], f[maxn][21];
struct edge{
    int next,to;
}e[2*maxe];
void Insert(int u,int v){
    e[++len].to=v;
    e[len].next=head[u];
    head[u]=len;    
}
void dfs(int u,int fa){
    dep[u] = dep[fa] + 1;
    for(int i=1; i<=dep[u]; i++) f[u][i] = f[f[u][i-1]][i-1];
    for(int i=head[u]; i; i=e[i].next){
        int v = e[i].to;
        if(v == fa) continue;
        dfs(v, u);
        f[v][0] = u;
    }
}
int lca(int u,int v){
    if(dep[u] < dep[v]) swap(u, v);
    int len = dep[u] - dep[v], k = 0;
    while(len){
        if(len & 1) u = f[u][k];
        k++; len >>= 1;
    }
    if(u == v) return u;
    for(int i=20; i>=0; i--){
        if(f[u][i] == f[v][i]) continue;
        u = f[u][i]; v = f[v][i];
    }
    return f[u][0];
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;scanf("%d%d",&x,&y);
        Insert(x,y);Insert(y,x);
    }
    dfs(1,0);
    int Q;scanf("%d",&Q);
    for(int i=1;i<=Q;i++){
        int u,v;scanf("%d%d",&u,&v);
        printf("%d\n",dep[u]+dep[v]-2*dep[lca(u,v)]);//求两个节点的LCA 
    }
}

原文链接: https://www.cnblogs.com/hzoi-poozhai/p/12817530.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    倍增算法

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/345771

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午3:27
下一篇 2023年3月2日 上午3:27

相关推荐