lca倍增

lca需要查询两个点的最近公共祖先,使用倍增预处理时间复杂度为O(nlogn),查询为O(logn)

点击查看代码
vector<int> dep;                  //记录树的深度
vector<vector<int>> up;            //记录倍增下第i个数的第第2^j级个祖先
vector<vector<int>> tree;          //要处理的树
int VAL=32;                        //设定二进制分解的最大值

//dfs处理得到up数组
void lcadfs(int x,int las){
    up[x][0]=las;                  //将第一个祖先保存在第0个
    dep[x]=dep[las]+1;             //递推深度=父节点深度+1

    //通过已有祖先来递推自己的祖先
    for(int i=1;i<VAL;++i){
        up[x][i]=up[up[x][i-1]][i-1];
    }
    //继续dfs处理
    for(auto v:tree[x]){
        if(v!=las){
            lcadfs(v,x);
        }
    }
}

//查询lca核心函数
int get_lca(int x,int y){
  //1.将深度较深的点跳跃到两点深度齐平
    if(dep[x]<dep[y])swap(x,y);
    int len=dep[x]-dep[y];
    for(int i=VAL-1;i>0;--i){
        if(len&(1<<i)){
            x=up[x][i];
        }
    }
    if(x==y)return x;              //深度齐平时为同一个点,那么最近公共祖先就是当前点

  //2.两点同时向上跳跃,找到最近公共祖先
    for(int i=VAL-1;i>=0;--i){     //从大往小跳跃能保证找到的lca不会超过正确的lca
        if(up[x][i]!=up[y][i]){
            x=up[x][i];
            y=up[y][i];
        }
    }
    return up[x][0];               //最终停在lca的下一层,所以返回父节点
}

**有时候题目要求使用倍增lca的同时,也要求用dfs预处理数据。这里就要记牢各个dfs调用哪个函数,否则就会像我一样猪脑过载代码攻击本人**
posted @ 2025-08-13 21:11  洛鸿  阅读(8)  评论(0)    收藏  举报