最近公共祖先 LCA (Lowest Common Ancestors)-树上倍增
树上倍增是求解关于LCA问题的两个在线算法中的一个,在线算法即不需要开始全部读入查询,你给他什么查询,他都能返回它们的LCA。
树上倍增用到一个关键的数组F[i][j],这个表示第i个结点的向上2^j层的结点。在RMQ-ST中用救是这样的数组。
在树上倍增中也是关键点。

如在上图中,我们要找结点8和7的LCA,从途中我们可以看出是3(这句估计是废话)。采用倍增的思想是这样的
首相判断结点U和V是否在同一层次,即是否深度相同。因为在深度相同后这样后,二者就可以同时向上跳某n层,去识别所到之点是否为它们的LCA。

如果深度较大(在底下的点),跳到较高的那个点后,发现二者重合了,那么恭喜,LCA已经找到了
另外底下的结点向上跳的步数也不是一步一层的,要不然太慢了。而是计算出U和V的高度差,按高度差的对数k(2^k)去跳,因而越来越接近高层结点,直到相等。

if(depth[u] < depth[v])
{
swap(u,v);//始终让U在最小边,便于理解
}
while(depth[u] != depth[v])//二者不再同一高度
{
u = father[u][lg[ depth[u]-depth[v]]]; //u向上跳 2^(二者高度差的对数)层
}
if(u==v)//重叠直接就是找到LCA
{
return u;
}
但是大多数情况不是这样的,它们往往不会重合,因此要开是同步向上跳。

以U结点到根结点的距离(U的深度为基准),取对数后为k,在这样去跳2^k层是肯定不会超过根上面的
但这样不保证是否错过了LCA,所以回退,k-1,重新跳2^(k-1)层,再去判断。直到U和V不等时,它们上一层的结点一定就是LCA了。再举个简单的例子吧

for(int j =lg[depth[u]];j>=;j--)//lg[depth[u]]表示u距离根结点的距离取对数
{
if(father[u][j] != father[v][j])//直到二者所跳的地方不一样
{
u = father[u][j];
v = father[v][j];
}
}
return father[u][];//返回u的father/上一层结点就是LCA
这个LCA需要以构建好树和计算出每个结点的深度的条件为基础的。
dfs就不细说了,这里只说一下这个语句
father[curnode][j] = father[father[curnode][j-]][j-];

最近公共祖先 LCA (Lowest Common Ancestors)-树上倍增的更多相关文章
- Leetcode之深度优先搜索(DFS)专题-1123. 最深叶节点的最近公共祖先(Lowest Common Ancestor of Deepest Leaves)
		
Leetcode之深度优先搜索(DFS)专题-1123. 最深叶节点的最近公共祖先(Lowest Common Ancestor of Deepest Leaves) 深度优先搜索的解题详细介绍,点击 ...
 - 树上两点的最近公共祖先问题(Least Common Ancestors)
		
概念: 对于有根树T的两个节点u,v,最近公共祖先LCA(T, u, v)表示一个节点 x, 满足 x 是 u , v 的祖先且 x 的深度尽可能的大.即从 u 到 v 的路径一定经过点 x. 算法: ...
 - 最近公共祖先(least common ancestors,LCA)
		
摘要: 本文主要介绍了解决LCA(最近公共祖先问题)的两种算法,分别是离线Tarjan算法和在线算法,着重展示了在具体题目中的应用细节. 最近公共祖先是指对于一棵有根树T的两个结点u和v,它们的LCA ...
 - 最近公共祖先(Least Common Ancestors)
		
题意: 给定一棵有根树T,给出若干个查询lca(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找一个节点,同时是u和v的祖先,并且深度尽可能大(尽可能远离树根).通常有以 ...
 - LeetCode 236. 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree)
		
题目描述 给定一棵二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义: “对于有根树T的两个结点u.v,最近公共祖先表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...
 - LCA最近公共祖先(least common ancestors)
		
#include"stdio.h" #include"string.h" #include"iostream" #include" ...
 - 最近公共祖先LCA(前置知识)
		
1.前言 最近公共祖先(Least Common Ancestors),简称LCA,是由Tarjan教授(对,又是他)提出的一种在有根树中,找出某两个结点u和v最近的公共祖先问题. 2.什么是最近公共 ...
 - POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
		
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
 - POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
		
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
 
随机推荐
- 【转载】    迁移学习(Transfer learning),多任务学习(Multitask learning)和端到端学习(End-to-end deep learning)
			
--------------------- 作者:bestrivern 来源:CSDN 原文:https://blog.csdn.net/bestrivern/article/details/8700 ...
 - Spring声明式事务如何选择代理方式?
			
Spring声明式事务如何选择代理方式 解决方法: 1.基于注解方法: <tx:annotation-driven transaction-manager="txManager&q ...
 - ABAP DEMO篇21 选择屏幕显示说明TEXT
			
实现方式1: *&---------------------------------------------------------------------**& Report YCX ...
 - 【Leetcode_easy】812. Largest Triangle Area
			
problem 812. Largest Triangle Area solution: class Solution { public: double largestTriangleArea(vec ...
 - 【Leetcode_easy】717. 1-bit and 2-bit Characters
			
problem 717. 1-bit and 2-bit Characters 题意:solution1: class Solution { public: bool isOneBitCharacte ...
 - iOS-app清除缓存
			
一直寻寻觅觅找app的清除缓存的方法,发现:并没有什么固定的方法,你既然有做对应的缓存机制,这个机制就应该有清除缓存的方法.例如如果你使用某个第三方的图片库,这个库有缓存机制,那么它就应该提供对应的清 ...
 - Docker镜像的构建(五)
			
目录 构建镜像 1.使用 commit 命令构建 1.1 运行一个要进行修改的容器 1.2 安装 Apache 软件包 1.3 提交定制容器 2.使用 Dockerfile 构建 2.1 我们的第一个 ...
 - 【c# 学习笔记】使用virtual和override关键字实现方法重写
			
只有基类成员声明为virtual或abstract时,才能被派生类重写:而如果子类想改变虚方法的实现行为,则必须使用override关键字. public class Animal { private ...
 - 【c# 学习笔记】c#中的类
			
1.什么是类: 在c#中类是一种数据结构,它可以包括数据成员.函数成员(方法.属性.事件.索引器.索引符.实例构造函数.静态构造函数和析构函数.及嵌套类型). 属性是,类中字段和方法的结合体,通过定义 ...
 - python中通过客户端IP拿到所在城市和当地天气信息—附带项目案例
			
熟悉老一代QQ的小伙伴可能都知道,很早以前的QQ,鼠标滑到头像的位置,你的位置和IP会在详情页显示,那么这个是如何做到的呢?下面我们就来玩一玩这个东西 首先,需求分析: 1.拿到客户端IP 2.通过I ...