码迷,mamicode.com
首页 > 编程语言 > 详细

浅谈LCA的在线算法

时间:2014-12-11 20:59:21      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:lca   rmq   st   

最近在学双连通分量,做到一个题,是LCA的,不会做就来学习了一下LCA,发现网上有好多资料,鱼龙混杂。推荐一篇因为他推荐了许多文章(感兴趣点击打开))

首先先借鉴一下他的一张图片

bubuko.com,布布扣

bubuko.com,布布扣

这基本就是这个lca的思想。

按照我的理解首先要dfs一边求出first 【u】,deep【u】,并且记录下first【u】所对应的u;

代码如下:

void dfs(int u ,int dep)
{
    vis[u] = true;
    ver[++tot] = u; 
    first[u] = tot; 
    deep[tot] = dep;
    for(int i=head[u]; i!=-1; i=edge[i].next)
		int v = edge[i].v;
        if( !vis[v] )
        {
            dfs(v,dep+1);
            ver[++tot] = u; 
            deep[tot] = dep;//这两句话表示dfs的时候还要回溯到上面
        }
}

然后继续RMQ预处理,ST算法,这个是在上面所说的博客模板

所谓ST算法就是

令dp【i】【j】为从下标i开始,长度为(1《《j)长的元素的最小值,那么状态转移方程就是

dp【i】【j】=min{dp【i】【j-1】,dp【i+(2<<(j-1))】【j-1】}

void ST(int len)
{
    int K = (int)(log((double)len) / log(2.0));
    for(int i=1; i<=len; i++) dp[i][0] = i;
    for(int j=1; j<=K; j++)
        for(int i=1; i+_pow[j]-1<=len; i++)
        {
            int a = dp[i][j-1] , b = dp[i+_pow[j-1]][j-1];
            if(deep[a] < deep[b]) dp[i][j] = a;
            else            dp[i][j] = b;
        }
}


RMQ,原理是令k为满足(1<<k)<=(r-l+1)的最大整数,则以 l 开头的,长度为2的k次方的区间长度覆盖了查询区间(l,r),由于是求最小值,所以没有关系,但是如果是累加的话,就要错,那么他的结果就是min(dp【l】【k】,dp【r+1-(1<<k)】【k】);

int RMQ(int x ,int y)
{
    int K = (int)(log((double)(y-x+1)) / log(2.0));
    int a = dp[x][K] , b = dp[y-pow[K]+1][K];
    if(deep[a] < deep[b]) return a;
    else            return b;
}

int LCA(int u ,int v)
{
    int x = first[u] , y = first[v];//查找出他最先出现的地方
    if(x > y) swap(x,y);
    int res = RMQ(x,y);//查询出的是他祖先的下标
    return ver[res];//查询出的是他的祖先
}
以上就是LCA转RMQ算法,然后还有一个tarjan离线算法,去学习喽

其实ST也是tarjan的,

要换床头画了

浅谈LCA的在线算法

标签:lca   rmq   st   

原文地址:http://blog.csdn.net/u013076044/article/details/41870751

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!