LCA

微笑、不失礼 提交于 2020-01-22 20:28:16

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