[最近公共祖先]tarjan算法实现LCA

本文详细介绍了如何使用Tarjan算法解决在有根树中找到两个节点的最近公共祖先(LCA)问题。算法为离线算法,通过存储询问、遍历并标记节点,并利用并查集进行操作。文章包括算法目的、流程解析以及代码实现,旨在帮助读者理解并掌握Tarjan算法在LCA问题上的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

本蒟蒻晚上闲得无聊,随便写写,感谢大家的观看
有错误请多多指出

正文

本文讲解如何使用 tarjan算法 求LCA
tarjan算法是一种 离线 算法

目的

首先了解一下 LCA

LCA(Least Common
Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先)

举个简单的例子

给大家一张图理解一下

示意图
一个 节点的祖先 可以是他的 父亲 也可以是他 自己

故图中

节点4 和 节点6 的最近公共祖先是 节点2
节点5 和 节点6 的最近公共祖先是 节点5
节点4 和 节点3 的最近公共祖先是 节点1
节点5 和 节点3 的最近公共祖先是 节点1

朴素算法

直接 暴力搜索 即可

求 节点A 和 节点B 的最近公共祖先

1.从 节点A 到 根节点,途中的 每个节点 标记 1

2.从 节点B 到 根节点,途中的遇到 第一个标记为1的点 就是最近公共祖先

实现较为简单,在此不多做阐述

下面开始讲解 tarjan算法

流程

需要了解 并查集

tarjan算法的具体流程如下

1.存储询问

由于是 离线算法

第一步需要存储询问

一般由于空间的要求使用 邻接表 + pair 存储,反正我用的是

2.遍历

从根节点向下遍历,遇到一个 未访问过的点 标记为 1

示意图

如果遇到 叶子结点 将当前 未访问过的点当前点 合并(此处并查集数组为 pre)然后看看当前节点是否有询问,没有询问直接将此结点标记为 2, 回溯

示意图

一直到

示意图

这时我们发现 节点6 和 节点4 有询问

如果遇到 叶子结点 并且与 其他节点 有询问,如果 其他节点 的标记为 2,则这两个节点的 最近公共祖先其他节点 并查集的祖先

示意图接着遍历即可

代码

代码的实现也相对简单

1.定义

前向星等基础操作,pre并查集 的数组,ans 数组 标记答案,vis 数组 是当前节点的 标记

using namespace std;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值