[算法整理]树上求LCA算法合集】的更多相关文章

1#树上倍增 以前写的博客:http://www.cnblogs.com/yyf0309/p/5972701.html 预处理时间复杂度O(nlog2n),查询O(log2n),也不算难写. 2#st表(RMQ) 首先对一棵树进行dfs,得到欧拉序列,记录下每个节点的第一次出现位置. (先序遍历这棵树,访问到的节点(无论是从深的一层返回还是父节点访问)就加入到序列中,序列长度为2 * n - 1) 根据欧拉序列神奇的特性,两个点第一次出现的位置之间,深度最小的一个点,是这两个点LCA(反正我是不…
算法介绍: 看到lca问题(不知道lca是什么自(bang)行(ni)百度),不难想到暴力的方法: 先把两点处理到同一深度,再让两点一个一个祖先往上找,直到找到一个相同的祖先: 这么暴力的话,时间复杂度基本上是$ o(n) $: 而观察一下暴力的过程,就会发现,其实一个一个祖先往上找效率非常的低,有没有能优化这一过程的方法呢?这时,强大的倍增就出现了,能够把暴力优化到$ o(log(n)) $: 倍增,简单说就是把一步一步跳替换成每次跳$ 2^i $个祖先: 做法: 先预处理出每个点的深度(df…
倍增LCA \(fa[a][i]\)代表a的第\(2^{i}\)个祖先. 主体思路是枚举二进制位,让两个查询节点跳到同一高度然后再向上跳相同高度找LCA. int fa[N][21], dep[N]; void dfs(int u, int f) { dep[u] = dep[f] + 1, fa[u][0] = f; for (int i = 1;i <= 20;i++) fa[u][i] = fa[fa[u][i - 1]][i - 1]; for (int i = head[u];i;i…
Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other. The boys decided to h…
//233 模板 LCA void dfs(int x,int f){ for(int i=0;i<E[x].size();i++){ int v = E[x][i]; if(v==f)continue; deep[v]=deep[x]+1; lca[v][0]=x; for(int j=1;j<maxm;j++){ int fa = lca[v][j-1]; if(fa==0)continue; lca[v][j]=lca[fa][j-1]; } dfs(v,x); } } int up(i…
倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. 关于倍增思想: 倍增的思想很简单:通过区间[1,2i-1]与[1+2i-1,2i(2i-1+2i-1)]求出区间[1,2i]. 所以它可以用于区间求最值,求和.而到了树上之后,就变成了,求它往上任意次的祖先. 而倍增求LCA,就是用到了倍增这个功能. 倍增求LCA算法思路: f[i,j],表示结点i…
本文整理了一些WooCommerce代码合集,方便查阅和使用,更是为了理清思路,提高自己.以下WooCommerce简称WC,代码放在主题的functions.php中即可. 修改首页和分类页面每页产品数量 每页显示多少产品默认跟随设置 » 阅读设置 » 博客页面至多显示的值,若要产品索引页和博文索引页使用不同的设置,可以使用下面的代码为产品索引页单独设置每页产品数. ? 1 add_filter( 'loop_shop_per_page', create_function( '$cols',…
LCA问题算是一类比较经典的树上的问题 做法比较多样 比如说暴力啊,倍增啊等等 今天在这里给大家讲一下tarjan算法! tarjan求LCA是一种稳定高速的算法 时间复杂度能做到预处理O(n + m),查询O(1) 它的主要思想是dfs和并查集 1.输入数据,找出根节点(或输入的)并将图存起来 2.输入需要查找的每一对点(两个点),也存起来(也存成图) 3.从根节点开始向它的每一个孩子节点进行深搜 4.同时开一个bool类型的数组记录此节点是否搜索过 5.搜索到p节点时先将p标记为已经搜索过了…
                                                                                                                                                         ----代码都是  HDU 2586  "How far away" 为例     倍增求LCA 树上倍增法. 设F[x,k] 表示x的2的k次方辈祖先,即 由x向上走2的k次方到达的…
[题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1<=wi<=10^9. [算法]最小生成树+倍增LCA+并查集 [题解]首先求出图的一个最小生成树M,则所有边分成树边和非树边. 一.对于非树边(u,v),假设u和v在最小生成树M上的路径的最大边权是Max.要保证这条边在最小生成树上,只要w(u,v)=Max-1. 下面证明w(u,v)=Max-1时…
概念 公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点 举个例子吧,如下图所示4和5的最近公共祖先是2,5和3的最近公共祖先是1,2和1的最近公共祖先是1. 算法 常用的求LCA的算法有:Tarjan/DFS+ST/倍增 其中 :ST和倍增都是在线的:Taijian是离线的 这里介绍离线的Tarjian算法 基本思想: 1.任选一个点为根节点,从根节点开始 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过 3.若是v还有子节点,返回2,否则下一步 4.合并v到u上 5.寻找与当前…
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4)一个点地一个点地往上跳,直到到某个点(3)和另外那个点(5)的深度一样 然后两个点一起一个点地一个点地往上跳,直到到某个点(就是最近公共祖先)两个点“变”成了一个点 不过有没有发现一个点地一个点地跳很浪费时间? 如果一下子跳到目标点内存又可能不支持,相对来说倍增的性价比算是很高的 倍增的话就是一次…
题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无意中看到树上莫队,只是拿来练练,没有想到这题的难点不在于树上莫队,而是判断LCA是否在两点之间的路径上的问题.耗时1天. 树上莫队的搞法就是: (1)DFS一次,对树进行分块,分成sqrt(n)块,每个点属于一个块.并记录每个点的DFS序. (2)将m个询问区间用所属块号作为第一关键字,DFS序作为第二关键字…
本文是网络资料整理或部分转载或部分原创,参考文章如下: 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,找…
tarjan算法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 这里我们使用tarjan算法离线算法解决这个问题. 离线算法,是指首先读入所有的询问(求一次LCA叫做一次询问),然后重新组织查询处理顺序以便得到更高效的处理方法.Tarjan算法是一个常见的用于解决LCA问题的离线算法,它结合了深度优先遍历和并查集,整个算法为线性处理时间. 总思路就是每进入一个节点u的深搜,就把整个树的一部分看作以节点u为根节点的小树…
这个Tarjan算法是求LCA的算法,不是那个强连通图的 它是 离线 算法,时间复杂度是 O(m+n),m 是询问数,n 是节点数 它的优点是比在线算法好写很多 不过有些题目是强制在线的,此类离线算法就无法使用了 另附上在线ST算法的链接: http://www.cnblogs.com/hadilo/p/5837517.html 直接上伪代码: 源代码中将询问用栈分节点一个个压入,而且克隆了单次询问,如询问 1 5 节点,则将 5 压入 1 的栈中,并且将 5 压入 1 的栈中 因为当询问时会有…
Attention 秋招接近尾声,我总结了 牛客.WanAndroid 上,有关笔试面经的帖子中出现的算法题,结合往年考题写了这一系列文章,所有文章均与 LeetCode 进行核对.测试.欢迎食用 本文将覆盖 「二进制」 + 「位运算」 和 Lru 方面的面试算法题,文中我将给出: 面试中的题目 解题的思路 特定问题的技巧和注意事项 考察的知识点及其概念 详细的代码和解析 开始之前,我们先看下会有哪些重点案例: 为了方便大家跟进学习,我在 GitHub 建立了一个仓库 仓库地址:超级干货!精心归…
倍增求 LCA 是在线的,而且比 ST 好写多了,理解起来比 ST 和 Tarjan 都容易,于是就自行脑补吧,代码写得容易看懂 关键理解 f[i][j] 表示 i 号节点的第 2j 个父亲,也就是往上走 2j 个节点 求 LCA 的时候先倍增让两点深度一样,再倍增求 另外丢两个链接,这两个有详细讲解 ST 算法 http://www.cnblogs.com/hadilo/p/5837517.html Tarajan 算法 http://www.cnblogs.com/hadilo/p/5840…
ACM算法模板 · 一些常用的算法模板-模板合集(打比赛专用)…
在此之前,我写过另一篇博客,是倍增(在线)求LCA.有兴趣的同学可以去看一看.概念以及各种暴力就不在这里说了,那篇博客已经有介绍了. 不会ST算法的同学点这里 ST(RMQ)算法在线求LCA 这个算法的思想,就是将LCA问题转化成RMQ问题. 怎么将LCA转成RMQ? 我们首先用dfsO(N)遍历一遍.比如下图: 得到一个dfs序(从儿子回到父亲也要算一遍): 1->2->4->7->4->8->4->2->5->2->6->9->6…
再开始前我们先普及一下简单的图论知识 图的保存: 1.邻接矩阵. G[maxn][maxn]; 2.邻接表 邻接表我们有两种方式 (1)vector< Node > G[maxn]; 这个是之前就定义了图的大小了,再下面使用的时候就不用对图的大小进行申请了, 但是因为是直接申请了大小 要对图进行初始化,因此可能在某些题目中这样使用的话会超时 (2)vector< vector<Node> > G; 这个是未定义大小,但是在使用之前要对其的大小内存进行申请. G.resi…
一.引子 本文搜集从各种资源上搜集高频面试算法,慢慢填充...每个算法都亲测可运行,原理有注释.Talk is cheap,show me the code! 走你~ 二.常见算法 2.1 判断单向链表是否有环 package study.algorithm.interview; /** * 判断单向链表是否有环? <p>Q1:判断是否有环? isCycle </> <p>Q2:环长? count </> <p>Q3: 相遇点? p1.data…
主要的最优(最短)路径算法: 一.深度优先算法:二.广度优先算法:三.Dijstra最短路径:四.floyd最短路径(待): 一.深度优先算法 图的深度优先搜索(Depth First Search),和树的先序遍历比较类似. 它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到. 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图…
百度百科 Definition&Solution 对于求树上\(u\)和\(v\)两点的LCA,使用在线倍增可以做到\(O(nlogn)\)的复杂度.在NOIP这种毒瘤卡常比赛中,为了代码的效率,常使用tarjan的离线LCA算法预处理各点复杂度.其复杂度为\(O(n~\alpha~(a))\) 在算法中,使用dfs遍历每个点.在回溯时,使用并查集维护每个被遍历到的点的已经回溯的最浅祖先.显然对于两个点,当一个点被后遍历到的时候,他们的LCA就是被先遍历到的点被维护的祖先. 在使用中使用并查集维…
首先,众所周知,求LCA共有3种算法(树剖就不说了,太高级,以后再学..). 1.树上倍增(ST表优化) 2.RMQ&时间戳(ST表优化) 3.tarjan(离线算法)不讲..(后面补坑啦!) 一.树上倍增 这种方法原理是这样的: 我们可以知道,最朴素的算法就是一步一步的并查集往上找,知道找到2个点并查集相同,即为LCA 但这种算法的时间效率为O(NM)看到0<n,m<5*10^5我们就知道一定会炸. 但是,我们可以发现给出树后,每个点的LCA及走到LCA的路径一定是固定的. 所以可以…
首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵树上距离最近的公共祖先节点. 所以LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径. 有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢? 答案是肯定的,很简单,按照人的亲戚观念来说,你的父亲也是你的祖先,而LCA还可以将自己视为祖先节点. 举个例子吧,如下图所示4和5的最近公…
LCA算法: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共的节点中,深度尽量深的点.还可以表示成另一种说法,就是如果把树看成是一个图,这找到这两个点中的最短距离. LCA算法有在线算法也有离线算法,所谓的在线算法就是实时性的,比方说,给你一个输入,算法就给出一个输出,就像是http请求,请求网页一样.给一个 实时的请求,就返回给你一个请求的网页.而离线算法…
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你不会吧:unamused:...) 思想 树上倍增嘛,顾名思义就是倍增 相信倍增大家都不默认,著名的rmq问题的$O(n*logn)$的解法就是利用倍增实现的 在树上倍增中,我们用 $f[j][i]$表示第$j$号节点,跳了$2^j$步所能到达的节点 $deep[i]$表示$i$号节点的深度 然后用…
原文链接http://www.cnblogs.com/zhouzhendong/p/7256007.html UPD(2018-5-13) : 细节修改以及使用了Latex代码,公式更加美观.改的过程中发现许多叙述上的问题,已经修改.然而得到这么多阅读量我真的是受宠若惊.于是我决定再补写一个在线$O(1)$查询的$RMQ$算法. 问题模型 对于一棵树,求两个节点的最近公共祖先(LCA). 如下图:(以下数字代表对应编号的节点) $1$ 和 $6$ 的 LCA 是 $8$ . $11$ 和 $1$…
LCA问题(Least Common Ancestors,最近公共祖先问题),是指给定一棵有根树T,给出若干个查询LCA(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找一个节点,同时是u和v的祖先,并且深度尽可能大(尽可能远离树根).LCA问题有很多解法:线段树.Tarjan算法.跳表.RMQ与LCA互相转化等. 一 LCA问题 LCA问题的一般形式:给定一棵有根树,给出若干个查询,每个查询要求指定节点u和v的最近公共祖先. LCA问题有两类解决思路: 在线算法,…