LCA

别说谁变了你拦得住时间么 提交于 2019-12-04 14:04:38

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倍

蒟蒻不会

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!