LCA是图论中常用的解决树形结构子问题的工具,这一问题一般需要用一个简短的子函数直接解决,但是这对于广大蒟蒻们仍然是一个不小的问题。

  LCA是指在树形结构中两点的最近公共祖先,对于这个问题,直接向上找事最直接的方法,但同时时间复杂度和数据给出的生成树的层数有关,最优情况是logN级别的,但是如果数据给出的是一条链就GG了,所以要用更优的方法写,一般来说,用的是log2N的操作,最糟糕的复杂度也是logN级别的,那如何实现这一过程捏,我这里有两种方法,和大家分享

  第一种:树上倍增

  具体方法是对于已经预处理好的f[i][j]数组来实现这一过程,预处理具体过程如下

 for(int j=;j<=n;++j)
f[][j]=father[j];
for(int i=;i<=;++i)
for(int j=;j<=n;++j)
f[i][j]=f[i-][f[i-][j]];

  这段代码需要稍加理解,f[i][j]表示第j个点的2的 i次方的父亲节点。因为一般数据给的不会特别大,所以在 i 的那重循环里,只要到20就够了,因为这是指数级的操作。

  这个预处理是常数级的O(N),只不过常数比较大。

  那么预处理结束后,我们接下来的操作就应该是对于每一组要求LCA的两个数,直接扔进子程序判断

  子程序如下

  

 int LCA(int x,int y)
{
if(dep[x]>dep[y])swap(x,y);
for(int i=;~i;--i)
if(dep[f[i][y]]>dep[x])y=f[i][y];
if(y==x)return x;
for(int i=;~i;--i)
if(f[i][y]!=f[i][x])y=f[i][y],x=f[i][x];
return f[0][x];
}

  这个子程序很简洁明了,只要会二进制拆分就很好理解,在第3行到第6行写的是输入的两点属于祖先与子孙关系,这时我们只要找一边的祖先节点就好啦;如果这两点属于不同子树,那就缩为同一深度。

  第7到第9行,代表两节点属于两颗子树这时只要不停的趋近就好了,因为我们的判断条件,所以在最后必须输出一个缩后点的父亲节点。

  第二种:欧拉序列

  这是一种更优的写法,主要思路是先将一颗树按欧拉序列处理,然后在每次对欧拉序列中这两点之间的点做一遍RMQ,RMQ的关键字是最小深度。

  但是这种写法较为复杂(我懒),所以代码没有给出,但是只要会RMQ的话这应该就是个较为简单的问题了。

  算法效率分析

  这种方法无论从时间复杂度还是空间复杂度来说都比树上倍增优,但事实上由于树上倍增极小的常数,所以这两个算法在时间复杂度上是相似的,但是在空间上来说欧拉序列更优,从另一个方面来说,树上倍增不仅可以求LCA,还可以顺便求一个路径最大权边之类的问题,并且编程复杂度优,所以一般来说树上倍增是比较常用的。

  有一道半模板题

  BZOJ3732

算法描述》LCA两三事(蒟蒻向)的更多相关文章

  1. Floyd-蒟蒻也能看懂的弗洛伊德算法(当然我是蒟蒻)

    今天来讲点图论的知识,来看看最短路径的一个求法(所有的求法我以后会写,也有可能咕咕咕) 你们都说图看着没意思不好看,那今天就来点情景             暑假,_GC准备去一些城市旅游.有些城市之 ...

  2. 蒟蒻的长链剖分学习笔记(例题:HOTEL加强版、重建计划)

    长链剖分学习笔记 说到树的链剖,大多数人都会首先想到重链剖分.的确,目前重链剖分在OI中有更加多样化的应用,但它大多时候是替代不了长链剖分的. 重链剖分是把size最大的儿子当成重儿子,顾名思义长链剖 ...

  3. 【一个蒟蒻的挣扎】最小生成树—Kruskal算法

    济南集训第五天的东西,这篇可能有点讲不明白提前抱歉(我把笔记忘到别的地方了 最小生成树 概念:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的 ...

  4. 【杂文】CSP2019蒟蒻AFO(假)记

    [杂文]CSP2019蒟蒻AFO(假)记 [初赛前 N 天] 时间:2019-10-15 今晚 \(2012\) 的初赛题做到心态爆炸,选择考计算机基础知识一脸懵逼,填空和后面一道大模拟直接跳过,最后 ...

  5. [BZOJ4636]蒟蒻的数列

    [BZOJ4636]蒟蒻的数列 试题描述 蒟蒻DCrusher不仅喜欢玩扑克,还喜欢研究数列 题目描述 DCrusher有一个数列,初始值均为0,他进行N次操作,每次将数列[a,b)这个区间中所有比k ...

  6. 一个蒟蒻对FFT的理解(蒟蒻也能看懂的FFT)

    建议同学们先自学一下"复数(虚数)"的性质.运算等知识,不然看这篇文章有很大概率看不懂. 前言 作为一个典型的蒟蒻,别人的博客都看不懂,只好自己写一篇了. 膜拜机房大佬 HY 一. ...

  7. 【杂文】NOIP2018 蒟蒻自闭记

    [杂文]NOIP2018 蒟蒻自闭记 都 \(9102\) 年了,谁还记得 \(2018\) 年的事啊 \(QAQ\) . 还有两个月就要去参加首届 \(CSP\) 了. 想着如果再不记下去年那些事儿 ...

  8. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 ||(离散化) + 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  9. 【蒟蒻の进阶PLAN】 置顶+持续连载

    看到周围神犇们纷纷列计划,本蒟蒻也决定跟随他们的步伐,计划大约是周计划吧,具体怎么安排我也不确定.. 2015.12.30 刚刚学习完最基础的网络流,需要进行这方面的练习,从简到难,有空余的话尝试学习 ...

随机推荐

  1. windows C++ 全局异常捕捉函数

    windows 核心编程中讲过 SEH 结构化异常处理 ::SetUnhandledExceptionFilter(MyUnhandledExceptionFilter); LONG WINAPI M ...

  2. windows服务是如何被调用的?

    1.服务介绍 操作系统在启动的时候,会启动一些不需要用户交互的进程.这些进程被称为服务.当操作系统启动后它就自动被运行. 2.组成 服务程序.服务控制程序(SCP,service control pr ...

  3. 有状态与无状态 cookie session

    服务器所维护的与客户交互活动的信息称为状态信息.不保存任何状态信息的服务器称为无状态服务器(stateless server),反之则称为有状态服务器(stateful server). 面向连接对应 ...

  4. Python笔记-2

    一.列表的定义及操作 列表是我们最以后最常用的数据类型之一,通过列表可以对数据实现最方便的存储.修改等操作. 1.列表的格式及赋值 列表,使用中括号括起来,元素之间用逗号隔开,列表中的元素具有明确的位 ...

  5. iOS UI调试工具 -- UIDebuggingInformationOverlay

    英文原文: http://ryanipete.com/blog/ios/swift/objective-c/uidebugginginformationoverlay/ 无意中看到iOS自带调试工具 ...

  6. Java实现三种常用的查找算法(顺序查查找,折半查找,二叉排序树查找)

    public class Search { public class BiTreeNode{ int m_nValue; BiTreeNode m_pLeft; BiTreeNode m_pRight ...

  7. test20181219 连续段的期望

    题意 连续段的期望 [问题描述] 小N最近学习了位运算,她发现2个数xor之后数的大小可能变大也可能变小,and之后都不会变大,or之后不会变小.于是她想算出以下的期望值:现在有 N个数排成一排,如果 ...

  8. Redis事件库源码分析

    由于老大在新项目中使用redis的事件库代替了libevent,我也趁着机会读了一遍redis的事件库代码,第一次读到“优美,让人愉快”的代码,加之用xmind制作的类图非常帅,所以留文纪念. Red ...

  9. jinja2的一些用法

    1.split用法以及乘法运算 {% set user_list=l.users.split(',') %} <tr> <td>{{ l.name }}</td> ...

  10. simple_one_for_one 和 one_for_one的区别

    参考这里http://blog.sina.com.cn/s/blog_77cb45a70102v1ja.html 用起来最直观的不同点 simple_one_for_one需要手工start_chil ...