dfs序求lca的讲解、相关常见错误及相关问题
本文暂时弃坑,以后会重构。
本文主要是用于警示自己避免犯错。
1|0相关博客
最近公共祖先 | st 表求 lca 别用欧拉序了!!!
冷门科技 —— DFS 序求 LCA
2|0算法讲解
这是以节点
我们在根节点进行 dfs,在 dfs 的开始将到达的节点加入一个序列的末尾中,就得到了所有节点拼成的一个序列,这个序列就是 dfs 序,节点在 dfs 序中的位置被称为节点的
对这颗树进行 dfs,可求得它的 dfs 序为
得到这个序列有啥用呢?如何求两个节点的 lca?
我们可以观察到某节点的祖先在 dfs 序中一定在该节点的前面,以某节点为根节点的子树的所有子节点(即除根节点外的所有节点)都在根节点的后面。所以不能直接在节点
我们来分类讨论,从一个简单的情况切入这个问题。
(下面的讨论默认
为 的祖先。
还是以上面那个图为例。
我们要找和 的 lca,显然 lca 为 。
观察从到 的 dfs 序,可以发现整个序列都是在 根节点为 的子树上进行的,一定经过 的子节点才到达 。
难道是直接返回从到 中深度最小的节点吗?
由前面的性质可知某节点的祖先在 dfs 序中一定在该节点的前面,万一不是 的祖先,这个方法就完全错了。
我们再回去观察一下。
从到 经过了 的孩子,也经过了 的祖先, 和 的 lca 一定是 的祖先,那我们找到 的祖先中除去 深度最小的那一个的父节点是不是就是 lca?
3|0参考代码
dfs 序求 lca 的参考代码如下。
4|0常见错误
- 无向边存储时少一次变成有向边。
太()()了。
- dfs 过程中忘记添加祖先及深度的记录。
这都能写错???
- 查找深度小的节点的函数写错。
我晕。
- ST 表建表写错
我怎么会在前面的 log 下标填
j-1
后填了个i+(1<<j)
。
- lca 求解过程中忘了写
u==v
的情况。 - lca 求解过程中忘了将
较大的 与 交换。
这两种情况倒是没写错过,不过以防万一还是加上。
- 直接把 lcason 返回。
st 表求的是 dfs 序中
所在位置加上 到 的位置中的深度最小的节点,并不是 lca,而是 lca 的孩子。
- 左移与加法运算的时候不加括号。
左移的优先级小于加法,不加括号导致运算的顺序错误,建议多加括号保险
5|0一些问题
- 我的
在求解过程中写错了,原本应该是下面的代码的前者(dfn[u]+1
到dfn[v]
这个序列的长度),却写成了后者(序列长度减去 ),但是没有被 hack 掉,是怎么回事?
可以看出这两种写法有区别当且仅当
dfn[v]-dfn[u]
为的倍数。
此时两种写法虽然 log 下标不同,但可以看出其覆盖范围是相同的。
看的出来,后者写法的两段区间刚好无缝衔接(衔接的两个端点差为),所以两种写法的输出都是正确的。
6|0后言
写的可能不是很完整,以后可能补充。
__EOF__

本文链接:https://www.cnblogs.com/LiJoQiao/p/17706287.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】