【专题】树上倍增

Tarjan LCA

http://blog.csdn.net/cdy1206473601/article/details/77104910

讲解

上次写了Tarjan LCA,但是当这棵树是一条链的话,时间复杂度就很高啦!所以,我们可以用倍增来解决。但是,在随机数据下,Tarjan是快于倍增的!
好吧,倍增思想就是设一个fa[i][j]表示i结点的第 2 j 级祖先。然后就可以通过向上的求解而使用到这个fa数组,实现倍增的效果。
形成这个fa数组,是用一个dfs来完成的。转移方程fa[i][j]=fa[fa[i][j-1]][j-1];

void dfs(int x)
{
    fa[x][0]=f[x];
    for (int i=1;i<=20;i++)
    {
        if (fa[x][i-1]<=1) break;
        fa[x][i]=fa[fa[x][i-1]][i-1];
    }
    int i=last[x],yy=0;
    vis[x]=true;
    while (i)
    {
        yy=tov[i];
        if (vis[yy]==false)
        {
            f[yy]=x;
            deep[yy]=deep[x]+1;
            dfs(yy);
        }
        i=next[i];
    }
}

然后就是倍增了,一开始寻找这两个点的深度,直到两个点的深度相等为止~

int lca_len(int x,int y)
{
    if (deep[x]<deep[y]) 
    {
        int t=x;
        x=y;
        y=t;
    }
    for (int i=20;i>=0;i--)//使其深度相等。
    {
        if (fa[x][i]!=0&&deep[y]<=deep[fa[x][i]]) 
            x=fa[x][i];
        if (x==y) break;
    }
    if (x==y) return x;
    for (int i=20;i>=0;i--)
    {
        if (fa[x][i]!=fa[y][i]) 
        {
            x=fa[x][i];
            y=fa[y][i];
        }
        if (x==y) break;
    }
    if (f[x]==f[y])
    {
        x=fa[x][0];
        y=fa[y][0]; 
    }
    return x;//最后Lca就是它们本身啦。
}

猜你喜欢

转载自blog.csdn.net/cdy1206473601/article/details/77104926