【转】 Tarjan求LCA

两种常用建图方法(vector实现邻接表,链式前向星) 文章目录前言一、vector实现邻接表1.优点2.思路3.实现代码二、链式前向星1.优点2.思路3.实现代码 前言 介绍两种建图的方法: 1.用vector实现的邻接表建图 2.链式前向星(邻接表的数组实现) 如果是一个稀疏图,在邻接矩阵中,会出现大量边的浪费,那么我们的思路是使用邻接表,但邻接表的实现方式也存在差异: 1.链表实现 2.vector实现 3.链式前向星 不同的实现方式在原理上存在一些差异,这里将介绍后两种方法,也是我们在做题时最常用的方法。 一、vector实现邻接表 1.优点 阅读详情

传送门: http://www.cnblogs.com/JVxie/p/4854719.html

太喜欢这篇解析啦,所以就搬到自己博客里来emmm

首先是最近公共祖先的概念(什么是最近公共祖先?):

    在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点。

    换句话说,就是两个点在这棵树上距离最近的公共祖先节点。

    所以LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径。

    有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢?

    答案是肯定的,很简单,按照人的亲戚观念来说,你的父亲也是你的祖先,而LCA还可以将自己视为祖先节点。

    举个例子吧,如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1。 

    这就是最近公共祖先的基本概念了,那么我们该如何去求这个最近公共祖先呢?

    通常初学者都会想到最简单粗暴的一个办法:对于每个询问,遍历所有的点,时间复杂度为O(n*q),很明显,n和q一般不会很小。

    常用的求LCA的算法有:Tarjan/DFS+ST/倍增

    后两个算法都是在线算法,也很相似,时间复杂度在O(logn)~O(nlogn)之间,我个人认为较难理解。

    有的题目是可以用线段树来做的,但是其代码量很大,时间复杂度也偏高,在O(n)~O(nlogn)之间,优点在于也是简单粗暴。

    这篇博客主要是要介绍一下Tarjan算法(其实是我不会在线...)。

    什么是Tarjan(离线)算法呢?顾名思义,就是在一次遍历中把所有询问一次性解决,所以其时间复杂度是O(n+q)。

    Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解。

    下面详细介绍一下Tarjan算法的基本思路:

      1.任选一个点为根节点,从根节点开始。

      2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。

      3.若是v还有子节点,返回2,否则下一步。

      4.合并v到u上。

      5.寻找与当前点u有询问关系的点v。

      6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。

    遍历的话需要用到dfs来遍历(我相信来看的人都懂吧...),至于合并,最优化的方式就是利用并查集来合并两个节点。

    下面上伪代码:

 


   1 Tarjan(u)//marge和find为并查集合并函数和查找函数
   2 {
   3     for each(u,v)    //访问所有u子节点v
   4     {
   5         Tarjan(v);        //继续往下遍历
   6         marge(u,v);    //合并v到u上
   7         标记v被访问过;
   8     }
   9     for each(u,e)    //访问所有和u有询问关系的e
  10     {
  11         如果e被访问过;
  12         u,e的最近公共祖先为find(e);
  13     }
  14 }

复制代码

    个人感觉这样还是有很多人不太理解,所以我打算模拟一遍给大家看。

    建议拿着纸和笔跟着我的描述一起模拟!!

    假设我们有一组数据 9个节点 8条边 联通情况如下:

    1--2,1--3,2--4,2--5,3--6,5--7,5--8,7--9 即下图所示的树

    设我们要查找最近公共祖先的点为9--8,4--6,7--5,5--3;

    设f[]数组为并查集的父亲节点数组,初始化f[i]=i,vis[]数组为是否访问过的数组,初始为0; 

    下面开始模拟过程:

    取1为根节点,往下搜索发现有两个儿子2和3;

    先搜2,发现2有两个儿子4和5,先搜索4,发现4没有子节点,则寻找与其有关系的点;

    发现6与4有关系,但是vis[6]=0,即6还没被搜过,所以不操作;

    发现没有和4有询问关系的点了,返回此前一次搜索,更新vis[4]=1;

    

    表示4已经被搜完,更新f[4]=2,继续搜5,发现5有两个儿子7和8;

    先搜7,发现7有一个子节点9,搜索9,发现没有子节点,寻找与其有关系的点;

    发现8和9有关系,但是vis[8]=0,即8没被搜到过,所以不操作;

    发现没有和9有询问关系的点了,返回此前一次搜索,更新vis[9]=1;

    表示9已经被搜完,更新f[9]=7,发现7没有没被搜过的子节点了,寻找与其有关系的点;

    发现5和7有关系,但是vis[5]=0,所以不操作;

    发现没有和7有关系的点了,返回此前一次搜索,更新vis[7]=1;

    

    表示7已经被搜完,更新f[7]=5,继续搜8,发现8没有子节点,则寻找与其有关系的点;

    发现9与8有关系,此时vis[9]=1,则他们的最近公共祖先为find(9)=5;

      (find(9)的顺序为f[9]=7-->f[7]=5-->f[5]=5 return 5;)

    发现没有与8有关系的点了,返回此前一次搜索,更新vis[8]=1;

 

    表示8已经被搜完,更新f[8]=5,发现5没有没搜过的子节点了,寻找与其有关系的点;

    

    发现7和5有关系,此时vis[7]=1,所以他们的最近公共祖先为find(7)=5;

      (find(7)的顺序为f[7]=5-->f[5]=5 return 5;)

    又发现5和3有关系,但是vis[3]=0,所以不操作,此时5的子节点全部搜完了;

    返回此前一次搜索,更新vis[5]=1,表示5已经被搜完,更新f[5]=2;

    发现2没有未被搜完的子节点,寻找与其有关系的点;

    又发现没有和2有关系的点,则此前一次搜索,更新vis[2]=1;

    

    表示2已经被搜完,更新f[2]=1,继续搜3,发现3有一个子节点6;

    搜索6,发现6没有子节点,则寻找与6有关系的点,发现4和6有关系;

    此时vis[4]=1,所以它们的最近公共祖先为find(4)=1;

      (find(4)的顺序为f[4]=2-->f[2]=2-->f[1]=1 return 1;)

    发现没有与6有关系的点了,返回此前一次搜索,更新vis[6]=1,表示6已经被搜完了;

    

    更新f[6]=3,发现3没有没被搜过的子节点了,则寻找与3有关系的点;

    发现5和3有关系,此时vis[5]=1,则它们的最近公共祖先为find(5)=1;

      (find(5)的顺序为f[5]=2-->f[2]=1-->f[1]=1 return 1;)

    发现没有和3有关系的点了,返回此前一次搜索,更新vis[3]=1;

    

    更新f[3]=1,发现1没有被搜过的子节点也没有有关系的点,此时可以退出整个dfs了。

   

    

Tarjan算法详解(AcWing 1174 受欢迎的牛) 题目描述: 每一头牛的愿望就是变成一头最受欢迎的牛。 现在有 N 头牛,编号从 1 到 N,给你 M 对整数 (A,B),表示牛 A 认为牛 B 受欢迎。 这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛 C 受欢迎。 你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。 输入格式 第一行两个数 N,M; 接下来 M 行,每行两个数 A,B,意思是 A 认为 B 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,B)。 输出格式 输出被除自己之外的 阅读详情

相关推荐

浅谈Tarjan算法求LCA

Tarjan是一个很厉害的人,不少算法(包括一些数据结构比如splay)都是他发明的…Tarjan求LCA是利用并查集的思想进行操作的首先我们有如下的思路void Tarjan(int u){ fa[u]=u; for(register int i=head[u];i;i=line[i].nxt){ int v=line[i].to; if(v!=fa

Monica 3844

最近公共祖先LCA(Tarjan算法)的思考和算法实现

LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ)       //由于这是第一篇博客..有点瑕疵...比如我把false写成了flase...看的时候注意一下!       //还有...这篇字比较多 比较杂....毕竟是第一次嘛 将就将...

diaoluo1817的博客 797

ASP.NET MVC5 C# Entity Framework 连接 Oracle 数据库

ASP.NET MVC5 C# Entity Framework 连接 Oracle 数据库创建数据库安装 Entity Framework配置数据库连接字符串添加实体模型类添加数据库上下文类添加控制器类运行测试 创建数据库 创建【全局数据库名】为 demodb 的Oracle数据库,用 SYSTEM 用户连接成功后创建【用户名】为 DJIANG 的用户,并授予该用户 DBA 角色 安装 Enti...

idjiang的博客 2537

trajan算法求lca 超级详细配图讲解

关于离线算法 (下面内容可以略过。) 离线算法其实就是将多个询问一次性解决。离线算法往往是与在线算法相对的。例如求LCA的算法中,树上倍增属于在线算法,在对树进行O(n)O(n)O(n)预处理后,每个询问用O(log2n)O(log_2n)O(log2​n)复杂度回答。而离线的Tarjan算法则是用O(n+q)O(n+q)O(n+q)时间将询问一次性全部回答。 详解 下面是一棵树,我们将以这棵树为例子讲解Tarjan算法,其中0号点为根。 假设对于这棵树的询问有4个,分别询问: LCA(2,8)LCA(2

m0_50219534的博客 1259

PPL文档——Excel制作的甘特图加上动态今日线

当很多项目需要跟踪进度时,我们介绍一种在Excel中创建甘特图。

qq_34777858的博客 7063

UVM环境复位--stop_sequences()

在UVM验证环境中, stop_sequences是一个用于强制终止所有正在运行的 Sequence 的方法,通常用于动态控制激励生成流程。1.通过uvm_config_db传递事件和严格的同步机制,此方案符适用于复杂复位场景和动态测试控制。组件耦合:Driver 和 Sequence 不再直接依赖env,通过标准接口通信。竞争条件:确保 Driver 完成清理后再终止 Sequence。代码健壮性:使用非阻塞操作和事件监听,避免死锁。

qq_42779035的博客 3013

【算法学习03】Tarjan&LCA

在有根树中,找出某两个结点u和v最近的公共祖先。一般有两种方法:树上倍增大跳求LCA和Tarjan离线算法求LCA,本篇主要描述Tarjan离线算法求LCA。

m0_46121643的博客 1344

Bioconductor核心包(GO.db等)安装失败排查指南:从版本冲突到网络优化

本文详细解析了Bioconductor核心包(如GO.db)安装失败的常见原因及解决方案,包括版本冲突、网络问题和依赖关系。通过版本检查、镜像配置和依赖管理等方法,帮助用户高效解决安装难题,提升R语言生物信息学分析的工作效率。

weixin_29066781的博客 425

用于求最近公共祖先(LCA)的 Tarjan算法–以POJ1986为例(转)

原文地址:https://comzyh.com/blog/archives/492/给定有向无环图(就是树,不一定有没有根),给定点U,V,找出点R,保证点R是U,V的公共祖先,且深度最深;或者理解为R离这两个点的距离之和最小.如何找出R呢?最一般的算法是DFS(DFS本是深度优先搜索,在这里姑且把深度优先遍历也叫做DFS,其实是一种不严谨的说法).先看一道赤裸裸的LCA:POJ 1330 Near

long-long-ago 1000

CVAEGAN实现锂离子电池EIS数据增强:基于健康状态的阻抗谱生成

本文提出了一种基于CVAEGAN的锂离子电池EIS数据增强方法。该方法结合了变分自编码器和生成对抗网络的优点,能够根据指定的健康状态(SoH)生成高质量的EIS阻抗谱数据。文章详细介绍了数据预处理流程、模型架构设计(包括编码器、解码器和判别器),并提供了完整的PyTorch实现代码。通过条件生成的方式,该方法可以有效解决电池健康评估中标注数据不足的问题,为基于数据驱动的电池诊断提供更丰富的训练样本。实验结果表明,生成的EIS数据具有良好的真实性和多样性,可用于增强电池健康状态评估模型的性能。

huanghm88的专栏 497

多智能体系统在军事仿真中的应用:AI人工智能战略推演

本文旨在全面解析多智能体系统在军事仿真领域的应用技术,重点探讨AI驱动的战略推演系统的设计原理和实现方法。研究范围涵盖从基础理论到实际应用的完整技术栈。本文采用从理论到实践的递进结构,首先介绍核心概念,然后深入算法实现,最后展示实际应用案例和未来展望。多智能体系统(MAS):由多个相互作用的智能体组成的分布式系统军事仿真(Military Simulation):通过计算机模拟军事行动和战争场景战略推演(Strategic Wargaming):通过模拟推演评估军事战略的有效性更高保真度的仿真。

AI天才研究院 1776

LCA模板 ( 最近公共祖先 )

LCA 有几种经典的求取方法、这里只给出模板,至于原理我完全不懂。 1、RMQ转LCA、复杂度O(n+nlog2n+m) 大致就是 DFS求出欧拉序 => 对欧拉序做ST表 => LCA(u, v) 即为 u、v 最先出现在欧拉序中的编号之间的最小值。 因为 LCA 的子树中必定有一个节点是 u,一个是 v,而且必定在两个节点到根节点的唯一路径上。 例如有欧拉序列 1...

234

【2026OD新机考】【哈希表】20260422-文章特征提取【Py/Java/C++/C/JS/Go六种语言OD真题】【欧弟算法】全网注释最详细分类最全的华子OD真题题解

90+天陪伴式学习,100+直播课时,300+动画图解视频,500+LeetCode经典题,500+华为OD真题/大厂真题,还有简历修改、模拟面试、陪伴小群、资深HR对接将为你解锁。这道题的本质是多集合交集问题的变形,属于非常典型的哈希表应用题。,储存全局的每个片段中,各个字符最少出现的次数。表示该字母并非所有片段的公共字母。,按照顺序构建答案即可。没有字母在所有三个字符串中都出现。每个字母在各字符串中都至少出现。次,所以结果中每个字母出现一次。这样,当上述循环结束后,最终。显然在上述代码中,如果字母。

weixin_48157259的博客 66

ZYNQ跨时钟域设计实战:AXI-Stream FIFO解决数据链路同步

在FPGA与SoC设计中,跨时钟域数据处理是可靠性设计的关键环节。当系统内存在多个不同频率的时钟域,如ADC采样时钟与DMA总线时钟不一致时,信号在跨越时钟边界时容易产生亚稳态,导致多bit数据采样错乱,进而引发数据帧错位或丢失。异步FIFO是解决多bit跨时钟域数据传递的常用方案,而AXI-Stream FIFO作为标准化的IP核,不仅内置了格雷码指针同步机制,还提供tvalid/tready握手协议,天然支持反压与流量控制,大幅降低了手写同步逻辑的复杂度和出错风险。在ZYNQ高速采集链路中,利用AXI-

weixin_30613727的博客 452

基于强化学习的多无人机路径规划

我们使用了Dueling Double Deep Q-Network(DDDQN)算法来训练智能体,这个算法在深度Q学习算法的基础上进行了升级,具有更快的收敛速度和更好的性能。本文提出了一种基于强化学习的算法,实现了多无人机路径规划,并提供相应的MATLAB代码。通过基于强化学习的多无人机路径规划算法,我们能够高效地解决复杂环境下的任务需求,并在实际应用中取得了良好的效果。首先,我们定义了状态空间和动作空间。实验结果表明,我们的方法能够有效地解决多无人机路径规划问题,提高了任务完成的效率和准确率。

DjjPython的博客 820

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Tarjan算法_LCA

首先我们要知道什么是LCA、深度优先生成树以及并查集在计算LCA的算法中我们有离线算法以及在线算法两种,我们这里使用的Tarjan算法是使用的是离线算法,即将所有的问题一次性输入,然后再一次性输出答案本人感觉这个算法的写法和Tarjan写法还是有很大差距的,相同的地方大部分是在思想上我们首先来举个例子,模拟一下这个算法的实现过程假设这是我们要计算的树,我们要计算7--8,5--6,5--2,4--...

A_Bo的博客 7578

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

tarjan离线、倍增在线求LCA

一、何为在线与离线? 在线算法:指它可以以序列化的方式一个个的处理输入,也就是说在开始时并不需要已经知道所有的输入。 离线算法:在开始时就需要知道问题的所有输入数据,而且在解决一个问题后就要立即输出结果。 例如,选择排序在排序前就需要知道所有待排序元素,然而插入排序就不必。 因为在线算法并不知道整个...

llyzznn的博客 278

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Tarjan入门⑤离线求LCA

前言: md,感觉LCA上我的学习顺序正好反过来了。先学的ST+欧拉序,后学的倍增。最后才学的Tarjan求LCA。 这个算法唯一不足就是离线的,但是一大好处就是实现起来超级简单。理解起来也很简单. 本质上就是一个dfs。 我们对每一个点开一个vector存询问。对于任意两个点u,vu,vu,v。dfs的时候要么先遍历u再遍历v.要么反之。所以我们需要对u,vu,vu,v都插入询问。 当访问到vvv时,若uuu已经被访问了,那么LCA(u,v)LCA(u,v)LCA(u,v)这个点一定是被访问且未结束访问的

qq_35577488的博客 244

Tarjan求LCA(最近公共祖先)

在有根树中,找出某两个结点u和v最近的公共祖先。一般有两种方法:树上倍增大跳求LCA和Tarjan离线算法求LCA,本篇主要描述Tarjan离线算法求LCA。5、寻找与当前节点u有关的查询,判断所查询的除了u以外的另一节点u’是否已访问。6、若u’已经被访问过,则u和u’的LCA就是u’已经被合并到的节点。2、遍历当前节点u的所有子节点(邻居节点)v,并置u节点为已访问。1、任选一个节点root作为根节点,从根节点开始遍历。3、若v还有子节点,则继续递归其子节点。4、并查集合并v到u上面。

2302_81590667的博客 739

洛谷 - P3379 【模板】最近公共祖先(LCA)(RMQ求LCA/Tarjan求LCA)

题目链接:点击查看 题目大意:给出一棵 n 个点组成的有根树,再给出 m 次询问,每次询问需要回答点 x 和点 y 的 lca 题目分析:今天新学了两种蛮有意思的求 LCA 的方法,总结一下四种方法各有利弊吧,实现复杂度参考我自己,如果有代码大佬能闭着眼随便写的话,忽略即可 Orz 树上倍增求LCA: 时间复杂度: 预处理:O( nlogn ) 查询:O( logn ) 空间复杂度:O( nlogn ) 实现复杂度:最简单 树链剖分求LCA: 时间复杂度: 预处理:O( n )

Falcon的博客 565

Tarjan算法离线求LCA

最近学习了Tarjan离线求LCA,写篇博客记录一下: 先贴出来:学习博客(讲的很好很详细~) 1.定义: LCA(Lowest Common Ancestor)最近公共祖先,即树上两个点最新的公共祖先节点 比如:lca(1,4)=1; lca(4,5)=3; lca(2,3)=1; 2.伪码: Tarjan(u){ for each(u,v){//遍历每一个u的...

m0_37579232的博客 325

LCA 与 tarjan 实现的原理

P3379 LCA模板 这里写到的是用tarjan与并查集求LCA。 首先回顾一下tarjan算法: 核心代码: for (int i = head[u]; i; i = edge[i].next) { int v = edge[i].to; tarjan(v); //递归返回,代表此时已经遍历完以 u 为节点的子树,u 根据每次递归层数,u 是不同的 } 它是一个可以将一张有向图或无向图遍历D...

qq_42873341的博客 375

Tarjan—离线求LCA

针对有询问的题目,在线做法为读入一个询问立刻给出输出;离线做法为读入所有询问后再给出输出。

weixin_62224014的博客 950

c++算法之高级数据结构篇 - Tarjan算法求LCA

Tarjan算法是一种高效的离线LCA(最近公共祖先)求解算法,巧妙结合DFS与并查集。其核心思路是在DFS过程中标记已访问节点,并通过并查集维护访问路径:当访问节点u时,若查询对象v已被访问,则LCA(u,v)即为v所在集合的代表节点;回溯时将子节点集合合并到父节点。算法时间复杂度接近O(n+Qα(n)),远优于在线算法,但需提前收集所有查询。典型实现使用邻接表存储查询,配合路径压缩优化的并查集,在DFS递归中完成查询应答。该算法体现了"整体处理"的离线思维优势,适合批量查询场景。

巴巴博一巴巴博一巴巴博一 1008

浅谈Tarjan——5(用Tarjan求LCA)

Tarjan算法不仅可以用来缩点,还可以用来求LCA。先介绍一下LCA,LCA(least common ancestors),是最近公共祖先的英文。指的是在一棵树中,点u和点v的最近的祖先。 如图,以黄点为树根:紫点和黑点的最近公共祖先就是绿点,白点和橙点的最近公共祖先就是橙点,灰点和蓝点的最近公共祖先是黄点。简而言之,LCA就是点u和v的父亲的父亲的父亲……第一个相交的父亲。LCA的算法有很多

stevensonson的博客 455

离线tarjan求lca的学习和所有习题

离线tarjantarjantarjan求lcalcalca的学习和所有习题 前言: 离线tarjantarjantarjan,跟tarjantarjantarjan求图的连通性没有关系,因为tarjantarjantarjan这个人tqltqltql,发明了各种数据结构和算法,所以用他的名字命名的算法太多了。 1.所谓离线就是给定若干个询问,不是每次给定一个询问就给出答案,而是在给定所有询问之后一次性将所有询问解决掉,然后每个O(1)O(1)O(1)的输出答案。 2.所谓离线tarjantarjantar

Harris-H的博客 686
上一篇: dp训练题集
下一篇: ST(Sparse Table)算法基本思路及实现
Wyt_code
博客等级 码龄9年 10粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值