洛谷 3379 最近公共祖先(LCA 倍增) 题意分析 裸的板子题,但是注意这题n上限50w,我用的边表,所以要开到100w才能过,一开始re了两发,发现这个问题了. 代码总览 #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #define nmax 1000100 #define demen 21 using namespace std; int fa[n…
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所以,我们可以用遍历路径的方法求 LCA. 但想想都知道啦,这种遍历的方法肯定too slow,最坏情况时可达到O(n),数据大点儿,就光荣TLE了. 所以我们高级的化身——倍增算法就出现了! 谈谈倍增—— 倍增简单来讲就是两个点跳到同一高度后,再一起往上跳,直到跳到一个共同的点,就能找到它们的最近公…
      树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4)一个点地一个点地往上跳,直到到某个点(3)和另外那个点(5)的深度一样 然后两个点一起一个点地一个点地往上跳,直到到某个点(就是最近公共祖先)两个点"变"成了一个点 不过有没有发现一个点地一个点地跳很浪费时间? 如果一下子跳到目标点内存又可能不支持,相对来说…
题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k(或者说是二进制中的1,10,100,1000...)辈祖先.求它时要利用性质:cur->Elder[i]==cur->Elder[i-1]->Elder[i-1].具体步骤看代码. #include <cstdio> #include <cstring> #inclu…
[简介] 解决LCA问题的倍增法是一种基于倍增思想的在线算法. [原理] 原理和同样是使用倍增思想的RMQ-ST 算法类似,比较简单,想清楚后很容易实现. 对于每个节点u , ancestors[u][k] 表示 u 的第2k个祖先是谁.很容易就想到递推式: ancestors[j][i] = ancestors[ancestors[j][i - 1]][i - 1];  根据二进制原理,理论上 u 的所有祖先都可以根据ancestors数组多次跳转得到,这样就间接地记录了每个节点的祖先信息. …
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为了方便起见,我们可以认为宇宙是一张有N 个顶点和M 条边的带权无向图,顶点表示各个星系,两个星系之间有边就表示两个星系之间可以直航,而边权则是航行的危险程度. sideman 现在想把危险程度降到最小,具体地来说,就是对于若干个询问(A, B),sideman 想知道从顶点A 航行到顶点B 所经过的…
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a rooted tree and a list of pairs of vertices. For each pair (u,v) the program determines the closest common ancestor of u and v in the tree. The closest co…
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each node is labeled with an…
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * (r,fa(lca))\). (树上差分) 求法 tarjan 离线算法, 总时间 \(O(n+q)\). (q表示询问次数) //利用前向星存储询问 struct te{int t,pr,lca;}edge[1000050],qedge[1000050]; int head[500050],pe…
倍增(爬树)算法,刚刚学习的算法.对每一个点的父节点,就记录他的2k的父亲. 题目为http://www.luogu.org/problem/show?pid=3379 第一步先记录每一个节点的深度用一个深搜,顺便对每个节点的20赋初值为自己的上一个节点. 第二步通过第一步的初始化对每个节点的2k次进行赋值为fa[i][j]=fa[ fa[i][j-1] ][ j-1 ];自己的j-1次幂的父节点的i-1次就是就是自己的j次幂. 第三步对询问做出处理 1,先判断x,y的深度,如果x比y浅就换位置…
根为r时x.y的公共祖先,就是lca(x,r),lca(x,y),lca(r,y)中深度最大的那一个,不要再在倍增的时候判来判去还判不对了... #include<bits/stdc++.h> #define pa pair<int,int> #define CLR(a,x) memset(a,x,sizeof(a)) using namespace std; typedef long long ll; ; inline ll rd(){ ll x=;; ;c=getchar();…
题意:求最近公共祖先. 解题关键:三种方法,1.st表 2.倍增法 3.tarjan 此次使用倍增模板(最好采用第一种,第二种纯粹是习惯) #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll…
声明 咳咳,进入重难点的图论算法之一(敲黑板): 题目: 洛谷 P3379 先放标程,施工ing,以后补坑!!!(实在太难,一个模板这么长 [ 不过好像还是没有 AC自动机 长哎 ],注释都打半天,思维过程和算法讲解又打一堆,能用到此模板的都至少 省选+  了,但这个又不能因为懒而不打,毕竟要复习)     var rmq:..,..] of longint; first,next,en,one,b:..] of longint; deep,a:..] of longint; i,j,k,m,n…
模板 吸取洛谷P3379的教训,我决定换板子(其实本质都是倍增是一样的),把vector换成了边表 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入样例#: 输出样例#: 洛谷P3…
水一发题解. 我只是想存一下树剖LCA的代码...... 以洛谷上的这个模板为例:P3379 [模板]最近公共祖先(LCA) 1.朴素LCA 就像做模拟题一样,先dfs找到基本信息:每个节点的父亲.深度. 把深的节点先往上跳. 深度相同了之后,一起往上跳. 最后跳到一起了就是LCA了. 预处理:O(n) 每次查询:O(n) 2.倍增LCA 朴素LCA的一种优化. 一点一点跳,显然太慢了. 如果要跳x次,可以把x转换为二进制. 每一位都是1或0,也就是跳或者不跳. 在第i位,如果跳,就向上跳2(i…
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了flase...看的时候注意一下! //还有...这篇字比较多 比较杂....毕竟是第一次嘛 将就将就 后面会重新改!!! 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句…
一.问题 求有根树的任意两个节点的最近公共祖先(一般来说都是指二叉树).最近公共祖先简称LCA(Lowest Common Ancestor).例如,如下图一棵普通的二叉树. 结点3和结点4的最近公共祖先是结点2,即LCA(3,4)=2 .在此,需要注意到当两个结点在同一棵子树上的情况,如结点3和结点2的最近公共祖先为2,即 LCA(3,2)=2.同理:LCA(5,6)=4,LCA(6,10)=1. 明确了题意,咱们便来试着解决这个问题.直观的做法,可能是针对是否为二叉查找树分情况讨论,这也是一…
转载来自:https://blog.andrewei.info/2015/10/08/e6-9c-80-e8-bf-91-e5-85-ac-e5-85-b1-e7-a5-96-e5-85-88lca-e7-9a-84-e4-b8-89-e7-a7-8d-e6-b1-82-e8-a7-a3-e6-96-b9-e6-b3-95/ 简述 LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点 u 和 v 最近的公共祖先(另一种说法,离树根最…
以下转自:https://www.cnblogs.com/JVxie/p/4854719.html 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵树上距离最近的公共祖先节点. 所以LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径. 有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢? 答案是肯定的,很简单,按照人的亲戚观念…
1.前言 最近公共祖先(Least Common Ancestors),简称LCA,是由Tarjan教授(对,又是他)提出的一种在有根树中,找出某两个结点u和v最近的公共祖先问题. 2.什么是最近公共祖先? 在一棵树中,每个结点都有他的父亲和祖先,而最近公共祖先就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵树上距离最近的公共祖先节点.结合下图和文字应该很好的诠释了最近公共祖先: PS:在LCA中,也可以将结点本身视为自己的祖先 在这颗以结点1为根的树中,4与5的最近…
LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. (来自百度百科) 一.倍增求LCA 预处理出距点u距离为2^0,2^1,2^2...的点作为f[u][0],f[u][1],f[u][2]... d[u]记录点u的深度 用二进制拆分的思想,让更深的点向上跳,直至与另一个点深度相同 此时,如果两个点重合了,那么那个浅的点本身就是最近公共祖先 若两个点没有重合,则继续按二进制拆分的思想,两个点同时跳相同高度,跳过了就跳短一些…
若图片出锅请转至here 概念 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵树上距离最近的公共祖先节点. 所以LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径. 有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢? 答案是肯定的,很简单,按照人的亲戚观念来说,你的父亲也是你的祖先,而LCA还可以将自己视为祖先节点. 举个…
UPDATE(20180822):重写部分代码. 1.前言 最近公共祖先(LCA),作为树上问题,应用非常广泛,而求解的方式也非常多,复杂度各有不同,这里对几种常用的方法汇一下总. 2.基本概念和暴力算法 最近公共祖先,顾名思义,指的是两个点的公有祖先中,最近的那个点.它显然不会作为一个单独的知识点拿出来考,但是在很多题目中,出现的频率很高,不同场合用不同的方法.先考虑最简单的做法.找祖先,显然是从所查询的两个点从下往上爬,直到两个点出现第一次重叠时,就是最近公共祖先了.首先我们预处理出所有点的…
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了flase...看的时候注意一下! //还有...这篇字比较多 比较杂....毕竟是第一次嘛 将就将就 后面会重新改!!! 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句…
前言: 给定一个有根树,若节点\(z\)是两节点\(x,y\)所有公共祖先深度最大的那一个,则称\(z\)是\(x,y\)的最近公共祖先(\(Least Common Ancestors\)),简称\(LCA\).它在许多与树相关问题中发挥较大作用 怎么求 以这题为例:luogu P3379 [模板]最近公共祖先(LCA) 朴素暴力 让深度更大的节点\(x\)向上走至与另一节点\(y\)在同一深度上,然后同时向上走直至相遇. 时间复杂度 \(O(N)\) 代码略 倍增优化 按照上面的思路,但是不…
目录 最近公共祖先 1.向上标记法 2.树上倍增法 3.Tarjan算法 最近公共祖先 定义:给定一颗有根树,若结点 z 既是 x 的祖先,也是 y 的祖先,则称 z 是 x,y 的公共祖先.在 x,y 所有的公共祖先中,深度最大的一个称为 x,y 的最近公共祖先,简称\(LCA(x,y)\). 求解最近公共祖先一般有三种解法:向上标记法,树上倍增法和 Tarjan 算法. 1.向上标记法 即对于任何两个结点 x , y ,分别从x y 向上走并标记它们所有经过的节点,第一次相遇的节点即为最近公…
什么是LCA? 祖先链 对于一棵树T,若它的根节点是r,对于任意一个树上的节点x,从r走到x的路径是唯一的(显然),那么这条路径上的点都是并且只有这些点是x的祖先.这些点组成的链(或者说路径)就是x的祖先链. LCA 根据名字来说,最近公共祖先就是两个点最近的相同祖先.实际上也可以理解为:两个点的祖先链深度最大的那个交点.极端的情况下,LCA可以就是两个点之一,或者就是根节点root. 顺便贴下eg: 树中节点8和7的LCA为3,节点4和7的LCA为1,节点5和2的LCA为2. *可以写成LCA…
Tarjan算法的详细介绍,请戳: http://www.cnblogs.com/chenxiwenruo/p/3529533.html #include <iostream> #include <stdio.h> #include <string.h> #include <algorithm> #include <string> #include <vector> /* AC 一开始读取数据的方式并不好,运行900多ms. 后来参照…
寻找最近公共祖先,示例如下: 1 /           \ 2           3 /    \        /    \ 4    5      6    7 /    \             \ 8    9           10 LCA(8,9)=4; LCA(5,8)=2; LCA(10,4)=1 思路一: 递归法 1.如果有一个结点是树的根结点,则必定不存在公共祖先:遍历二叉树每个结点,检查其左右子树是否包含指定的两个结点: 2.遍历二叉树每个结点,检查其左右子树是否包…
[题目链接:http://caioj.cn/problem.php?id=1236][40eebe4d] 代码:(时间复杂度:nlogn) #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> using namespace std; const int maxn = 100005; struct node { int to,next; } edges[max…