LCA求法--Tarjan与倍增与RMQ

LCA,即最近公共父亲节点。相信大家都知道,就不再赘述了。




--Tarjan(离线)



思想:DFS+并查集

这个算法与tarjan本人没什么关系,只是因为思想与另一个tarjan算法相像,所以叫tarjan。




图示出自http://www.cnblogs.com/JVxie/p/4854719.html,请自动无视flase与false的区别吐舌头

首先,我们先DFS,对于当前DFS到任意一个节点,我们该如何找到关于它与另外一个节点的LCA呢??


显然只可能是他自己或者他的任意一个祖先。

然后呢?


我们以8为例,看一下它与别的节点的LCA吧


1.如果这个点是在5下的一个点(包括自己) ,则8与它的LCA为5(7,9,5)

2.如果这个点是在2下的一个点(包括自己),且这个点不在上一步中,则8与它的LCA为2(2,4)

3.如果这个点是在1下的一个点(包括自己),且这个点不在之前的步骤中,则8与它的LCA为1(1,3,6)


然后算法过程就比较好理解了,先贴一段伪代码:

void dfs(int u)
{ 设定u为已访问
    遍历u的所有儿子v
        若未访问过,则dfs(v),合并u所在集合和v所在集合为一个新集合,设定新集合的祖先为u
        若访问过则不再访问
    检查跟这个u点有关的查询(u,v)
        若v已访问,则lca = v所在集合的祖先(u的祖先为自己)
        若v未访问不做处理
}
访问自然是按DFS顺序的



模板题:https://www.luogu.org/problem/show?pid=3379

代码:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值