花式找LCA

10 篇文章 0 订阅
5 篇文章 0 订阅

前言

今天开始做noi p 难度的天天爱跑步这道题。虽然我现在还并没有把它杠掉,但是由于学到一种新式LCA找法,于是心血来潮写下了这篇博文。本文中的LCA找法均来自本人学过或听说过的算法。

正文

①倍增

用倍增算法解决LCA时,以数组fa[i][j]表示以节点i开始,向上跳2j个点所达到的位置。
计算fa数组时,先从小到大枚举2的次方数j,再枚举每一个点i,fa[fa[i]][j-1]即为fa[i][j]的值。
具体实现可参考本人博文货车运输

②tarjan

本人仅仅是听说过tarjan这种万能的算法可以求LCA,然而并没有学过,也懒得学辣,所以度娘出一篇文章供大家参考。见这里

③树链剖分

这才是本文最想介绍的一种算法。
如果没有学过树链剖分,本人安利一个不错的视频click here
由于树链剖分将完整的树剖成了一条条互不重复的链,并且记录了当前链的顶部和当前点的父亲,所以我们可以利用这种性质进行求解。
具体实现:
①当两个点的top值不同时,即两个点不在同一条链内,比较两个点的top的deep,将其中top的deep值较大的那个点跳到top的父亲处,重复①。否则进行②。
②返回两个点中deep值较小的那个点的位置,求解完毕。
是不是很短?

inline int LCA(int u,int v)
{
    while(top[u]!=top[v])
      if(deep[top[u]]<deep[top[v]]) v=f[top[v]];
      else u=f[top[u]];
    return deep[u]<deep[v]?u:v;
}

UPD:原先返回的是错误的,已更正,希望大家不要被我这个智障误导

就是这么短!
为什么是正确的呢?
自己画几个图感受一下就明白辣
当两个点不在同一条链中的时候,两个点永远不可能重合,也就不在其LCA处。
其他的我就不用解释了叭!

最后

本人介绍了三种LCA的求解方法,如果单纯是考LCA,tarjan应当常数比较小;但如果已经树链剖分过了,那么一定不要再使用倍增等算法了,比如遥远的国度这道题,我见到的所有人几乎都用的倍增,但是我用了树链剖分自带的LCA以后速度rank1= =。所以要灵活选取算法。
普及组小盆友请随意选择
貌似普及组考纲中并没有LCA这个考点嘛

The end.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值