suoi31 最近公共祖先2 (倍增lca)】的更多相关文章

根为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();…
最近公共祖先问题(LCA)是求一颗树上的某两点距离他们最近的公共祖先节点,由于树的特性,树上两点之间路径是唯一的,所以对于很多处理关于树的路径问题的时候为了得知树两点的间的路径,LCA是几乎最有效的解法. 首先是LCA的倍增算法.算法主体是依靠首先对整个树的预处理DFS,用来预处理出每个点的直接父节点,同时可以处理出每个点的深度和与根节点的距离,然后利用类似RMQ的思想处理出每个点的 2 的幂次的祖先节点,这就可以用 nlogn 的时间完成整个预处理的工作.然后每一次求两个点的LCA时只要对两个…
题意:求最近公共祖先. 解题关键:三种方法,1.st表 2.倍增法 3.tarjan 此次使用倍增模板(最好采用第一种,第二种纯粹是习惯) #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll…
LCA也是很经典的内容了,我这个蒟蒻居然今天才开始弄QAQ 我太弱啦! 照例先上定义——————转自维基百科 在图论和计算机科学中,最近公共祖先是指在一个树或者有向无环图中同时拥有v和w作为后代的最深的节点.在这里,我们定义一个节点也是其自己的后代,因此如果v是w的后代,那么w就是v和w的最近公共祖先. 最近公共祖先是两个节点所有公共祖先中离根节点最远的,计算最近公共祖先和根节点的长度往往是有用的.比如为了计算树中两个节点v和w之间的距离,可以使用以下方法:分别计算由v到根节点和w到根节点的距离…
[题目链接: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…
描述 上上回说到,小Hi和小Ho用非常拙劣--或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求. 但正如我们所能想象到的--这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择: 其一是购买更为昂贵的服务器,通过提高计算机性能的方式来满足需求--但小Hi和小Ho并没有那么多的钱:其二则是改进他们的算法…
传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求. 但正如我们所能想象到的……这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择: 其一是…
题目链接:http://hihocoder.com/problemset/problem/1062 题意裸,有个trick,导致我当年做的时候一直在WA... 那就是出现这种没有出现在关系中,但是依然可以知道他们关系的输入样例: LinDaiyu LinDaiyu 应该输出自己. #include <bits/stdc++.h> using namespace std; ; int n, m, q; map<string, int> id; string di[maxn]; vec…
Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 重要事情说三遍!!!!! 2019.7.16更新 笔记再次完善,感谢[Ichinose]大佬提出的好问题,并且修改了代码部分的错误注释. 笔记再次完善,感谢[Ichinose]大佬提出的好问题,并且修改了代码部分的…
目录 最近公共祖先 1.向上标记法 2.树上倍增法 3.Tarjan算法 最近公共祖先 定义:给定一颗有根树,若结点 z 既是 x 的祖先,也是 y 的祖先,则称 z 是 x,y 的公共祖先.在 x,y 所有的公共祖先中,深度最大的一个称为 x,y 的最近公共祖先,简称\(LCA(x,y)\). 求解最近公共祖先一般有三种解法:向上标记法,树上倍增法和 Tarjan 算法. 1.向上标记法 即对于任何两个结点 x , y ,分别从x y 向上走并标记它们所有经过的节点,第一次相遇的节点即为最近公…
本文是网络资料整理或部分转载或部分原创,参考文章如下: https://www.cnblogs.com/JVxie/p/4854719.html http://blog.csdn.net/ywcpig/article/details/52336496 https://baike.baidu.com/item/最近公共祖先/8918834?fr=aladdin 最近公共祖先,简称LCA(Lowest Common Ancestor): 所谓LCA:是当给定一个有根树T时,对于任意两个结点u.v,找…
寻找最近公共祖先,示例如下: 1 /           \ 2           3 /    \        /    \ 4    5      6    7 /    \             \ 8    9           10 LCA(8,9)=4; LCA(5,8)=2; LCA(10,4)=1 思路一: 递归法 1.如果有一个结点是树的根结点,则必定不存在公共祖先:遍历二叉树每个结点,检查其左右子树是否包含指定的两个结点: 2.遍历二叉树每个结点,检查其左右子树是否包…
前言 ​ "倍增",作为一种二进制拆分思想,广泛用于各中算法,如\(ST\)表,求解\(LCA\)等等...今天,我们仅讨论用该思想来求解树上两个节点的\(LCA\)(最近公共祖先) "倍增"是什么东西? ​ 倍增就是"成倍增加"的意思,比如\(1\)倍增后变成了\(2\),\(2\)倍增后就变成了\(4\),\(4\)变成\(8\),以此类推... 实现 一直向上LCA ​ 在讲真正的倍增之前,我们先来说说最朴素的\(LCA\),对于需要求解的…
与正文无瓜的前言 身为一个高一才开始学的OIER,现在才开始恶补模板,感觉今年就要退役了. 不想刷题了滚过来写写博客<-------极端危险的思想. 引入 LCA(Lowest Common Ancestors),即最近公共祖先,听名字就知道这是与树上两个节点有关的东西. 它的定义就是两个点最近的公共祖先(废话),同时它也是树上一个节点到另一个节点的最短路中经过的深度最小的点. 如图,2就是8与9的最近公共祖先,7就是10和12的最近公共祖先. 那么LCA有什么用呢? 举个例子,我们可以利用LC…
[试题描述] 求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor). 二叉查找树 如果该二叉树是二叉查找树,那么求解LCA十分简单. 基本思想为:从树根开始,该节点的值为t,如果t大于t1和t2,说明t1和t2都位于t的左侧,所以它们的共同祖先必定在t的左子树中,从t.left开始搜索:如果t小于t1和t2,说明t1和t2都位于t的右侧,那么从t.right开始搜索:如果t1<t< t2,说明t1和t2位于t的两侧,那么该节点t为公共祖先. 如果…
Q:为什么我在有些地方看到的是最小公共祖先? A:最小公共祖先是LCA(Least Common Ancestor)的英文直译,最小公共祖先与最近公共祖先只是叫法不同. Q:什么是最近公共祖先(LCA)? A:最近公共祖先的概念是很好理解的.首先,你需要脑补出一棵树(它可以是二叉树,也可以是多叉树.)之后,请你再在你脑补出的树上任取两个点.每个点都可以到达树根,且到达的路径是唯一的,既然两个点都可以到达树根,那么根无疑是这两个点的公共祖先.然而,根却不一定是这两个点的最近公共祖先,相反,离根距离…
概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介绍一下倍增算法 我们需要一个数组de[i]来表示每一个节点i的深度,用另一数组parent[i][j]来表示每一节点j向上走2的i次方是哪个节点 我们首先在初始化中算出每个点的深度和它的上一个点是什么(用parent[0][i]表示) 在此后我们进行倍增的处理:parent[1][j]=parent…
      树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4)一个点地一个点地往上跳,直到到某个点(3)和另外那个点(5)的深度一样 然后两个点一起一个点地一个点地往上跳,直到到某个点(就是最近公共祖先)两个点"变"成了一个点 不过有没有发现一个点地一个点地跳很浪费时间? 如果一下子跳到目标点内存又可能不支持,相对来说…
洛谷 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…
CodeVs.2370 小机房的树 ( LCA 倍增 最近公共祖先) 题意分析 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子,他们不想花费太多精力.已知从某个节点爬到其父亲节点要花费 c 的能量(从父亲节点爬到此节点也相同),他们想找出一条花费精力最短的路,以使得搞基的时候精力旺盛,他们找到你要你设计一个程序来找到这条路,要求你告诉他们最少需要花费多少精力 首先用倍增处理树形结…
1.最近公共祖先:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.的祖先且x的深度尽可能大. 2.朴素算法:记录下每个节点的父亲,使节点u,v一步一步地向上找父亲,直到找到相同的“祖先”,即是所求的答案,时间复杂度O(n). 3.优化算法(倍增法):利用二进制的思想,想办法使一步一步向上搜变成以2^k地向上跳.所以定义一个P[][]数组,使p[i][j]表示节点i的2^j倍祖先,因此p[i][0]即为i的父亲.我们可以得到一个递推式p[i][j]=p[p…
一.前人种树 博客:最近公共祖先 LCA 倍增法 博客:浅谈倍增法求LCA 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 代码: const int MAXN = 10010; const int DEG = 20; struct Edge { int to,next; }edge[MAXN*2]; int head[MAXN],tot; void addedge(int u,int v) { edge[tot].to = v; edge[tot].ne…
P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入…
转自大佬博客 : https://blog.csdn.net/lw277232240/article/details/72870644 描述:倍增法用于很多算法当中,通过字面意思来理解 LCA是啥呢  在一棵树当中 lca表示的是两个节点最近公共祖先, 大家看这课树哈节点5 ,3的lca就是1,13和11的LCA就是6.节点8,12的lca就是8,那么我们如何通过被增来实现LCA呢. 首先请大家认真看下面的分析. depth[x],表示x节点的深度. 大家看下这个数组 grand[x][i] ,…
题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤: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\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\)的区间值.在这些预处理结果的基础上,我们可以进一步求出任意长度区间的答案. 比如区间最值问题\((RMQ)\)就可以使用倍增解决.对于每个起始点,预处理长度为\(2^n\)的区间最值.之后每段区间都可以以此求出,如: \(f(1,7)=\max(f(1,4),f(3,7))\) 以上是最简单的一个举例.在计…
之前在澡堂学过这么个东西,听课时理解非常透彻,然后做题时是这种状态: 因为并没有切板子题,最近切掉以后看同桌,他默默地说了一句话: 我是什么时候A的来着... 我当时就心态爆炸... 现在来进行简单整理 我发现想黈之前的博客非常难,因为之前写的博客都是什么东西啊 其实我本身来讲也能理解(疯狂为下次培训不好好整理找理由) 以为澡堂给的时间其实并不多,看上去有一中午加一晚上, 但是每天学的东西都非常之多,要是把每个板子题都切下,博客中的最详细内容就只能gu掉了... 心塞... (突然发现自己水了这…
倍增法求lca(最近公共祖先) 基本上每篇博客都会有参考文章,一是弥补不足,二是这本身也是我学习过程中找到的觉得好的资料 思路: 大致上算法的思路是这样发展来的. 想到求两个结点的最小公共祖先,我们可以先把两个的深度提到同一水平,在一步一步往上跳,直到两个结点有了一个公共祖先,依照算法流程,这就是least common ancestor. 但是如果这样一步步地往上未免太让人着急,为了提高一下效率,便不再每次只跳一步,而跳\(2^i\)步.一般的,先这样蹦蹦跳跳跳上去直到两个结点相平,在两个一起…
P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入…
pa[a][j] 表示 a 结点的 2^j倍祖先(j = 0时 为直接父亲,j = 1时为父亲的父亲……) 1.首先预处理出所有结点的深度值dep和父亲结点 void dfs(int u, int f, int d) { dep[u] = d; pa[u][] = f; ; i < G2[u].size(); i++) { edge& e = E[G2[u][i]]; int v = e.u == u ? e.v : e.u; if(v != f) { dfs(v, u, d+); } }…