LCA 的若干种求法

LCA 的若干种求法

对于有根树来说,LCA 指两点的最近公共祖先。求法较多,下面选取一些有特色的求法来讲解。

树链剖分法

特点: O ( n ) O(n) O(n) 预处理,单次 O ( log ⁡ n ) O(\log n) O(logn)

首先对树进行轻重链剖分预处理。

在求两个点 u , v u,v u,v 的 LCA 时,分为以下两种情况:

  • u , v u,v u,v 在同一条重链上,则两者为祖孙关系,返回深度小的点;
  • u , v u,v u,v 不在同一条重链上,则可以把更深的那条重链跳过去,LCA 不变。

由于重链数量为 O ( log ⁡ n ) O(\log n) O(logn),所以单次复杂度为 O ( log ⁡ n ) O(\log n) O(logn)

提交记录

倍增法

特点: O ( n log ⁡ n ) O(n\log n) O(nlogn) 预处理,单次 O ( log ⁡ n ) O(\log n) O(logn),常数大,空间大,所以被上者吊打。

改进自逐步上移法。大致分为两个过程:

  • 先让深度大的点上移,直到两个深度相等。
  • 再让两个点一直向上移动相同步,直到到同一个点。

这两过程均可使用倍增加速。

提交记录

dfs 序+RMQ 法

原来是打算用欧拉序+RMQ 法的,但好像改用 dfs 序也挺好的,常数更小一点。

特点: O ( n log ⁡ n ) O(n\log n) O(nlogn) 预处理,单次 O ( 1 ) O(1) O(1)

首先我们对整棵树进行一次 dfs 得到 dfs 序。假如我们求的是 u , v u,v u,v 的 LCA (其中 d f n u < d f n v dfn_u<dfn_v dfnu<dfnv)。无非两种情况:

  1. u u u v v v 在其 LCA 的两棵子树内。
    这种情况下, u , v u,v u,v 的 LCA 的时间戳并不在 [ d f n u , d f n v ] [dfn_u,dfn_v] [dfnu,dfnv] 中。但是, v v v 所在子树离 LCA 最近的节点一定在 [ d f n u , d f n v ] [dfn_u,dfn_v] [dfnu,dfnv] 中,且一定为深度最小点。我们只需要求出 [ d f n u , d f n v ] [dfn_u,dfn_v] [dfnu,dfnv] 中深度最小点,再取其父亲,就是 LCA 了。
  2. u u u v v v 的祖先。这个时候 LCA 就是 u u u

我们综合 1 2,只要取出 [ d f n u + 1 , d f n v ] [dfn_u+1,dfn_v] [dfnu+1,dfnv] 中的深度最小点,再取其父亲即可。这个可以用 st 表处理。

提交记录

Tarjan 法的

还不会

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日居月诸Rijuyuezhu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值