首页 > 其他分享 >LCA(最近公共祖先)学习笔记

LCA(最近公共祖先)学习笔记

时间:2023-04-24 09:45:53浏览次数:52  
标签:标记 祖先 dfs int 笔记 LCA 倍增 节点

前言

没想到干完lca的时间比tarjan的还要长(我不能这么弱下去了!!)

前置知识

  • dfs序
    这东西有点类似于时间戳(dfn),但是它分为两部分(回溯之前和回溯之后)。并且dfs序还分为两种。这里只介绍一倍的dfs序。
    image
    如上图,蓝色代表左端点,红色代表右端点,(学过Tarjan的都知道),蓝色其实就是这棵树的dfn(时间戳,即遍历节点的顺序),很显然是在递归之前标记好的,相应地,红色就是在回溯时标记好的。这样标记的意义显而易见,每一个节点都可以表示为一个闭区间,配合树状数组线段树可在树上实现链上操作,比如说更新某个节点节点及以下的子树的权值,以及查询某颗子树的权值和。详见例题1例题2

    代码如下:

    点击查看代码
    void dfs(int x, int fa) {
    	in[x] = ++cnt; // in[x] 表示节点 x 的左端点
    
    	for (int i = 0; i < ver[x].size(); ++i) {
    		int y = ver[x][i];
    
    		if (y == fa || in[y]) continue;
    		dfs(y, x);
    	}
    
    	out[x] = cnt; // out[x] 表示节点 x 的右端点
    }
    

    二倍的dfs序较为简单,在这里只给出图片和代码,大家自行理解,不再做详细介绍。
    image

    代码如下:

    点击查看代码
    void dfs(int x, int fa) {
    	in[x] = ++cnt; // in[x] 表示节点 x 的左端点
    
    	for (int i = 0; i < ver[x].size(); ++i) {
    		int y = ver[x][i];
    
    		if (y == fa || in[y]) continue;
    		dfs(y, x);
    	}
    
    	out[x] = ++cnt; // out[x] 表示节点 x 的右端点
    }
    
  • 倍增
    字面意思就是成倍增长。这里我们只介绍倍增思想的衍生算法ST表求解RMQ(区间最值问题),倍增LCA将会在下面的板块单独介绍。
    倍增一般是以 \(2^n, n \in \mathbb Z\) 为基准而成倍增长。据此思想设 \(f[\ i\ ][\ j\ ]\) 表示从下标为 \(i\) 的位置到下标为 \(i + 2^j - 1\) 的位置的最值,显然这段区间长是 \(2^j\) ,亦可得边界 \(f[\ i\ ][\ 0\ ] = a[\ i\ ]\) ,其中 \(a[\ ]\) 为原序列。既然边界下标是小的,我们就可以用小的推大的,怎么推,用倍增。递推式为 \(f[\ i\ ][\ j\ ] = max(f[\ i\ ][\ j - 1\ ],\ f[\ i + 2^{j - 1}\ ][\ j - 1\ ])\) ,还原一下就是区间 \([\ i,\ i + 2^j - 1\ ]\) 的最值由 \([\ i,\ i + 2^{j - 1} - 1\ ]\) 和 \([\ i + 2^{j - 1},\ i + 2^{j} - 1\ ]\) 这两个长度为 \(2^{j-1}\) 区间取得最值。
    若查询区间 \([\ l, \ r\ ]\) 的最值,其区间长 \(len = r - l + 1\) ,令 \((int)t = \log_2len\),我们可以从区间 \([\ l,\ l + 2 ^ t - 1\ ]\) 和 \([\ r - 2 ^ t + 1\ ,\ r\ ]\) 取得最值,可证得这两段区间能覆盖整个要查询的区间以及不超过边界。
    PS:这东西本质上就是倍增优化DP。

LCA的朴素算法

最最最最最最朴素的算法就是从下向上标记。显然,最最最最最最坏的情况就是一条链,两个查询的节点一个是根节点,一个是叶节点。设一共有 \(n\) 个节点,则每次查询时间复杂度是 \(O(n)\) ,多次查询的话必定超时无疑。

LCA的倍增算法(在线)

其实就是倍增对朴素算法的小优化。朴素算法每次只往上跳一个,而倍增优化每次往上跳 \(2^i\) 个。我们先要用dfs预处理出来每个节点的 \(2^i\) 倍祖先是谁,考虑最坏的情况(树退化成链),\(i_{max} = \log_2n\) ,显然每次查询的最坏时间复杂度是 \(O(\log_2n)\) ,设共有 \(m\) 组查询,那么总的时间复杂度为 \(O((n + m)\log_2n)\) ,可以接受。

LCA的Tarjan算法(离线)

这是用并查集对朴素算法的小优化。在树上跑一遍dfs,将正在访问的节点标记为 \(1\) ,已经访问完的标记为 \(2\) ,还没访问的标记为 \(0\) 。在跑dfs同时遍历与当前节点(一定被标记为 \(1\) )有关的查询,如果要查询的另一个节点被标记为 \(2\) ,那么就用并查集找到其祖先,这个找到的祖先就是二者的LCA。因为这棵树上的所有被标记为 \(1\) 的节点和它们之间的一条边构成一条链,并且正在访问的被标记为 \(1\) 的节点一定在链的最末端(最顶端一定是根节点),通过并查集找到的 \(1\) 一定是正在访问的本身或其它 \(1\) 节点。找到答案以后就把它存起来就好,跑完dfs以后将答案统一输出。

标签:标记,祖先,dfs,int,笔记,LCA,倍增,节点
From: https://www.cnblogs.com/Chronologika/p/17337843.html

相关文章

  • CountDownLatch 学习笔记
    1.概念CountDownLatch是在JDK1.5的时候被引入的,位于java.util.concurrent并发包中,CountDownLatch叫做闭锁,也叫门闩。允许一个或多个线程一直等待,直到其他线程执行完成后再执行。2.工作原理CountDownLatch通过一个计数器来实现的。计数器的初始化值为线程的数量。每当一个线程......
  • Fine-Grained学习笔记(1):卷积,FFT
    Fine-Grained,在算法复杂度理论中特指,对各类算法的复杂度,进行(相较于P与NP的粗粒度分类的)细粒度分类,例如,证明某问题存在$n^2/\logn$的算法.Fine-Grained是一个新兴领域,其研究前景可看作是计算机科学学科中的石墨烯与钙钛矿(误).本系列主要参考UniversityofIllinoisa......
  • 【学习笔记】2-SAT
    适应性问题存在若干命题\(p_i\),以及若干形如\(x_{k_1}\lorx_{k_2}\lor\dots\lorx_{k_n}\)的\(s_k\),其中\(x_i\)为\(p_i\)或\(\lnotp_i\)其中一个。要求是否存在一个命题的取值集合使得条件\(s\)均成立,其中每个条件最多包含\(n\)个命题,这样的问题称为n-SAT问......
  • Java学习笔记(四)
    1、break、continue、return的区别(1)break常在switchcase中使用,也可以在循环中使用。作用:当遇到break,则结束当前整个switchcase语句或者当前整个循环。执行外面语句。(2)continue:只能在循环中使用。作用是结束当前这一次循环,执行下一次循环。(3)return:在方法中使用,作用是结束当前......
  • JS课堂笔记(4.17-4.21)
    一、循环 1.在程序中,一组被重复执行的语句被称为循环体,能否继续重复执行,取决于循环的终止条件。由循环体及循环的终止条件组成的语句,被称为循环语句。2.循环执行的过程是①第一次循环:第一次赋值,然后条件判断,执行循环体,最后执行累计。②非第一次循环:条件判断,执行循环体,最后执行......
  • 《综述图论中连通性及相关问题的一些处理方法》笔记
    基本概念边/点割集:若边集\(E'\)使得割掉这些边之后\(u\tov\)不连通,则\(E'\)是\((u,v)\)的边割集。类似地定义点割集。边/点连通度:若任意\((u,v)\)的割集大小都至少是\(s\),则\(u,v\)是\(s-\)边连通的。类似地定义点连通度。Menger定理:\(u\tov\)的边连通......
  • C51笔记-郭天祥-第二章 从点灯大师开始
    第2章  Keil软件的使用及流水灯设计 Keil的用法:用Keil建立工程;            工程配置;            C51单片机程序软件仿真、单步、全速、断点设置和变量查看等; 用一个完整的C51程序操控LED亮灭;调用库函数实现流水灯;蜂鸣器与继电器的操作方法,集......
  • Django笔记二十九之中间件介绍
    本文首发于公众号:Hunter后端原文链接:Django笔记二十九之中间件介绍这一节介绍一下Django的中间件。关于中间件,官方文档的解释为:中间件是一个嵌入Django系统的request和response的钩子框架,是一个能够全局改变Django输入/输出的系统。我们可以这样理解,一个request......
  • nginx学习笔记
    开始简介Nginx是一款高性能的开源Web服务器和反向代理服务器,它能够提供可扩展性、高可用性和高性能。优点更快单次请求更快,高峰期也更快高扩展性极具扩展性,它由多个不同功能、不同层次、不同类型且耦合度极高的模块组成,这种低耦合的设计,造就了它庞大的第三方模块高可......
  • 「学习笔记」2-SAT问题
    SAT是适定性\(\text{(Satisfiability)}\)问题的简称。一般形式为k-适定性问题,简称k-SAT。而当\(k>2\)时该问题为NP完全的。所以我们只研究\(k=2\)的情况。2-SAT,简单的说就是给出\(n\)个集合,每个集合有两个元素,已知若干个\(<a,b>\),表示\(a\)与\(b\)矛盾(其中......