最近公共祖先(LCA)——离线Tarjan算法+并查集优化

一. 离线Tarjan算法

LCA问题(lowest common ancestors):在一个有根树T中,两个节点的最近公共祖先,指的是二者的公共祖先中深度最高的节点。给定任意两个树中的节点,求它们的最近公共祖先。

对于二分查找树、二叉树,可以用普通的dfs实现,但对于多叉树、查询次数频繁的情况下,离线Tarjan算法的优点就显现出来了。由于对树上所有节点只进行一次遍历,因此需要提前指定所有查询,所以才称为offline。

算法思路是:每次处理一个节点时,先递归处理其儿子节点,保证:若查询的节点pair均在该子树中,则处理完这个节点后,这些查询也已经处理完毕,否则其中一个节点在另一个子树中,这对节点的公共祖先至少应该是的父节点。具体是对每个节点,都维护一个集合,每当一个节点处理完毕,就与其父节点所在集合进行合并。处理完毕指的是:以该节点为根节点的子树中的所有节点都被访问过并且返回了。因此以某个元素为代表元的集合内,保存的都是当前已经处理完毕的子孙节点。

算法的伪代码如下:初始时每个节点颜色均为white

LCA(u)
1	MakeSet(u)
2	u.ancestor := u
3	for each v in u.children do
4		LCA(v)
5		Union(u, v)
6		Find(u).ancestor := u
7	u.color := black;
8	for each v such that {u, v} in P do
9		if v.color == black
10			print "Tarjan's lowest common Ancestor of " + u + 
				  " and " + v + " is " + Find(v).ancestor + "."</span>
		

下面首先对算法导论中的习题进行证明:

(1)证明:对每一对,第10行恰执行一次

证明:因为每个节点只调用一次LCA,对任意节点对,不失一般性,假设先被处理完&

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值