lca学习心得

lca求树上两点最近的公共祖先。

对于树上两点最近的公共祖先,我们首先能想到的办法,就是暴力,如果深度不相同先调整到相同深度,如果深度相等了,祖先不同的话,就继续向上找,直到找到相同的公共祖先。

但是这样的方法,显然速度太慢,那么我们该怎么寻找两个点最近的公共祖先呢?

我们可以处理一颗树上的所有点将其所有的2的次幂的祖先处理出来,放在一个数组中,寻找两个点共同公共祖先时,首先将两个点深度调到一致,然后我们两个点一起向上找直到找到共同的公共祖先。

代码:

首先预处理深度,公共祖先数组:

void dfs(int pre,int rt)
{
    depth[rt]=depth[pre]+1;
    fa[rt][0]=pre;
    for(int i=1;i<20;i++)
    {
        fa[rt][i]=fa[fa[rt][i-1]][i-1];
    }
    for(int i=0;i<edge[rt].size();i++)
    {
        if(edge[rt][i]!=pre)
        dfs(rt,edge[rt][i]);
    }
}

之后直接,lca搜索公共祖先即可:

int lca(int x,int y)
{
    if(depth[x]<depth[y])
    swap(x,y);
    for(int i=18;i>=0;i--)
    {
        if(depth[x]-(1<<i)>=depth[y])
        x=fa[x][i];
    }
    if(x==y)
    return x;
    for(int i=18;i>=0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        x=fa[x][i],y=fa[y][i];
    }
    return fa[x][0];
}

lca的简单应用:

找一棵树上两个点最短距离:

我们事先处理过深度数组,那么对于一直的两个点,根据其深度即可求得两个点最短距离:

depth[x]+depth[y]-2*depth[lca(x,y)]即可;

int dis(int x,int y)
{
    int lca=LCA(x,y);
    if(lca==0)
    {
        lca=0;
    }
    return depth[x]+depth[y]-2*depth[lca];
}

猜你喜欢

转载自blog.csdn.net/Black__wing/article/details/82429316