淺談樹上倍增

#Tarjan LCA
http://blog.csdn.net/cdy1206473601/article/details/77104910
#講解
上次寫了Tarjan LCA,但是當這棵樹是一條鏈的話,時間複雜度就很高啦!所以,我們可以用倍增來解決。但是,在隨機數據下,Tarjan是快於倍增的!
好吧,倍增思想就是設一個fa[i][j]表示i結點的第2j2^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就是它們本身啦。
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章