LCA算法实现方法介绍

LCA算法是用于在一个树或者一个图中,找出两个节点的最近的公共祖先。

关于离线算法和在线算法的区别:

    对于一个在线算法是指它可以以序列化的方式一个个的处理输入,也就是说在开始时并不需要已经知道所有的输入。如插入排序

    对于一个离线算法,在开始时就需要知道问题的所有输入数据,而且在解决一个问题后就要立即输出结果。如选择排序

   (选择排序在排序前就需要知道所有待排序元素,然而插入排序就不必。)

第一种方法:

1、先通过DFS算法,对树或图进行预处理,获得一棵树或一个图中所有节点的深度及其父节点。然后根据已知的信息,不断的将两个节点往回迭代,直到找到了同一高度,同一个父节点,此时这个节点便是他们两点的公共祖先了。

int  LCA(int u,int v) //在某一个图中,找出u,v的公共祖先
{
         if(h[u]>h[v]) // 深度不同,单个节点向上攀爬,到与另一节点同一高度
         {
                   while(h[u]>h[v]) //提示:在这个循环里做文章,就可以解决很多环的问题
                   {
                            u=pre[u]; //pre[u]表示u的父节点
                   }
         }
         else if(h[v]>h[u])
         {
                   while(h[v]>h[u])
                   {
                            v=pre[v];
                   }
         }
         while(u!=v)  //深度相同了,同时向上攀爬,直到成了同一点
         {
                   u=pre[u];
                   v=pre[v];
         } 
return  u; //找到了公共祖先
}

第二种方法tarjan离线算法

   该算法思路从根开始深搜遍历树,每当回溯到一个节点时,那就意味着已经完成了该节点子树的遍历,显然这个节点就是子树中所有点以及其本身的最近公共祖先,以此类推到整个树。对于一个点,只有完成了其子树的遍历,我们才改变其父节点的值,即把子树所形成的集合与当前结点的集合合并,并将当前结点设为这个集合的祖先(运用并查集的思想)。这样,对于每次询问(就是给出两点标号,求两点间最短距离),假设为 A 和 B,我们搜到 A (或B)时,如果 B (或A)已经被访问过,那么这个时候最近公共祖先必然是B(或A)所在集合对应的祖先C,因为我们对A的访问就是从最近公共祖先C转过来的,并且在从C的子树B转向A的时候,我们已经将B的祖先置为了C,同时这个C也是A的祖先,那么C必然是A、B的最近公共祖先。

算法示例:

(1)POJ 1470  题目地址:http://poj.org/problem?id=1470  解答地址:http://blog.csdn.net/geniusluzh/article/details/6609685

(2)HDU2586   题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2586  解答地址:http://blog.csdn.net/jarily/article/details/8947928


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值