LCA(最近公共祖先)

例题
给定一颗多叉树,求两个点的最近公共祖先

dfs遍历预处理出每个节点的父亲信息,存在fa[x][0]中。
fa[x][j]为x点向上走2^i步所到的节点
depth[x]为x点所在的深度

void dfs(int x,int f)
{
    v[x] = 1;
    dpth[x] = dpth[f] + 1;
    fa[x][0] = f;
    for (int i = 1; i <= t;i++)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    for (int i = head[x]; i;i=net[i])
    {
        int v1 = ver[i];
        if(v[v1])
            continue;
        dfs(v1, x);
    }
}

每个点向上走任意步数能到达的点都能通过倍增数组表示出来。
1、利用2进制拆分思想,向上调整深度大的点y,直到和点x深度相同
l 从大到小枚举k,比较x和fa[y][k],一直调整到和x深度相同f=f[y][k]。
2、调整到同一深度后:此刻x和fa[y][k ]相等,说明x为LCA
否则说明两个点还没走过LCA,两个点同时
向上往深度大于LCA的点跳
跳到最后会停留在LCA下面
3、最后再向上跳一步就是LCA
代码

int lca(int x,int y)
{
    if(dpth[x]>dpth[y])
        swap(x, y);
    for (int i = t; i >= 0;i--)
        if(dpth[fa[y][i]]>=dpth[x])
            y = fa[y][i];
    if(x==y)
        return x;
    for (int i = t; i >= 0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}
posted @ 2020-08-19 15:33  DSHUAIB  阅读(120)  评论(0)    收藏  举报