LCA求法--Tarjan与倍增与RMQ

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




--Tarjan(离线)



思想:DFS+并查集

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


LCA求法--Tarjan与倍增与RMQ_第1张图片


图示出自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

代码:

你可能感兴趣的:(LCA)