注:求解LCA有至少7种做法,如果让我全部写出来,我会死掉的。这里我只讲朴素和倍增

注:抄别人的代码不是一个好习惯 我不会告诉你这个代码我可以弄了一点点失误进去

版权声明:倍增代码使用的是李白莘莘学子的代码,原文点这里

下面列举一下LCA的做法:朴素算法,倍增,RMQ,用欧拉序列转化为RMQ ,太监(tarjan)和动态树(看这里有惊喜)

RMQ以后将分块时可能会去提(前提我记得)(180+行),太监其中有dfs序和邻接链表,不讲(90+行)。树剖以后讲到会提(很快就讲)

//朴素算法

#include

#define MAXN 100100

using namespace std

int n,head[MAXN],dep[MAXN],cnt=0,q,fa[MAXN];

struct edge

{

int nxt,to;

}e[MAXN];

void add(int u,int v)

{

e[++cnt].nxt=head[u];

e[cnt].to=v;

head[u]=cnt;

}

void dep_ccl(int u,int f)//预处理fa[]数组及深度

{

dep[u]=dep[f]+1;//原点深度等于他爸的深度加一

fa[u]=f;

for(int i=head[u];i!=0;i=e[i].nxt)//基操遍历

{

int v=e[i].to;

if(v!=f)dep_ccl(v,u);

}

}

int main()

{

scanf("%d",&n);

for(int i=1;i

{

int a,b;

scanf("%d%d",&a,&b);

add(a,b);

add(b,a);

}

dfs(1,0);

scanf("%d",&q);

for(int i=1;i<=q;i++)

{

ans=0;

int a,b;

scanf("%d%d",&a,&b);

while(a!=b)//LCA

{

if(dep[a]>=dep[b])a=fa[a];

else b=fa[b];

}

cout<

}

return 0;

}

//倍增

#include//万能头

#define MAXN 200200

using namespace std;

int n,m,s,cnt=0,head[MAXN],dep[MAXN],f[MAXN][23];

int a,a;

struct edge{

int next,to;

}e[4*MAXN]

void e_add(int u,int v)//链式前向星存图

{

cnt++;

e[cnt].next=head[u];e[cnt].to=v;head[u]=cnt;

e[++cnt].next=head[v];e[cnt].to=u;head[v]=cnt;

}

void dfs(int u,int father)//对应深搜预处理f数组

{

dep[u]=dep[father]+1;

for(int i=1;(1<

{

f[u][i]=f[f[u][i-1]][i-1];

}

for(int i=head[u];i;i=e[i].next)//遍历树

{

int v=e[i].to;

if(v==father)continue;//双向图需要判断是不是父亲节点

f[v][0]=u;

dfs(v,u);

}

}

int lca(int x,int y)

{

if(dep[x]

for(int i=20;i>=0;i--)//从大到小枚举使x和y到了同一层

{

if(dep[f[x][i]]>=dep[y])x=f[x][i];

if(x==y)return x;

}

for(int i=20;i>=0;i--)//从大到小枚举

{

if(f[x][i]!=f[y][i])//尽可能接近

{

x=f[x][i];y=f[y][i];

}

}

return f[x][0];//f[y][0]也ok

}

int main(){

scanf("%d%d%d",&n,&m,&s);

for(int i=1;i

{

scanf("%d",&a1);scanf("%d",&a2);

e_add(a1,a2);//链式前向星存图

}

dfs(s,0);//预处理

for(int i=1;i<=m;i++)

{

scanf("%d %d",&a1,&a2);

printf("%d\n",lca(a1,a2));//求两个节点的LCA

}

}

首先,是我们的朴素算法O(n^2)。

首先,将树上每个节点的深度预处理出来,还有他们的霸霸预处理出来。

方法:爆搜。开两个函数变量:u(遍历到的节点)和f(u他爸)。将整棵树遍历一遍。

遍历过程中,将fa[u](即u他的fuqin节点)赋值为f,dep[u](即u的深度)赋值为dep[f]+1(即u他爸的深度,以前遍历出来过)

然后在主函数中,定义两个指针a,b,最开始的时候指向要求LCA的那两个点。

每次让更深的那个指针往上跳一个点。即a=fa[a]||b=fa[b]

然后在两指针指向同一个点时,这个点就是他们的LCA,原因你自己想想。这不是废话吗

倍增,就是在朴素算法的基础上,呈倍 增上去。同样,有一个fa数组,需要预处理出来。

其中fa[i][j]表示i的第\(2^j\)个祖先。利用fa的定义(即fa[i][j]表示i的第\(2^j\)个祖先)用循环预处理出fa数组。

其中有个地方做一点点解释

for(int i=20;i>=0;i--)//从大到小枚举使x和y到了同一层

{

if(dep[f[x][i]]>=dep[y])x=f[x][i];

if(x==y)return x;

}

for(int i=20;i>=0;i--)//从大到小枚举

{

if(f[x][i]!=f[y][i])//尽可能接近

{

x=f[x][i];y=f[y][i];

}

}

这里i为什么是20到1呢?先看代码

我们发现f的第二位的下标都是i,意味着一定是求某个数的\(2^i\)个祖先。

如果你担心,你尽可以开31->1甚至63->1,不过一般题目不会给那么大的数据,一般是2^20左右的,这就是这样来的。

树如何找共同祖先_树的运用:求树上共同祖先LCA相关推荐

  1. 最近公共祖先_[LeetCode] 236. 二叉树的最近公共祖先

    题目链接: https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree 难度:中等 通过率:57.2% 题目描述: ...

  2. java并查集找朋友圈_并查集求朋友圈最大人数

    #include #include using namespace std ; int findRoot( int set[ ], int s ) { if (s == set[s]) return ...

  3. 字典树哇 AC自动机哇 = _ =

    字典树哇 AC自动机哇 = _ = 例题 HDU 1251 统计难题 解题思路 : 字典树 原理:按照每个根向下发散 形成一棵 树 这个题 需要在每一个字母处都做统计 (求前缀单词) 开一个 二维数组 ...

  4. java二叉树是什么_树的基本概念以及java实现二叉树

    树具有的特点有: (1)每个结点有零个或多个子结点 (2)没有父节点的结点称为根节点 (3)每一个非根结点有且只有一个父节点 (4)除了根结点外,每个子结点可以分为多个不相交的子树. 树的基本术语有: ...

  5. 3层b+树索引访问磁盘次数_【112期】面试官:为什么选择B+树作为数据库索引结构?谈谈你的理解

    本文同步Java知音社区,专注于Java 阶段汇总集合:++小Flag实现,一百期面试题汇总++ 背景 首先,来谈谈B树.为什么要使用B树?我们需要明白以下两个事实: [事实1] 不同容量的存储器,访 ...

  6. 二叉树第i层中的所有结点_讲透学烂二叉树(二):图中树的定义amp;各类型树的特征分析...

    日常中我们见到的二叉树应用有,Java集合中的TreeSet和TreeMap,C++ STL中的set.map,以及Linux虚拟内存的管理,以及B-Tree,B+-Tree在文件系统,都是通过红黑树 ...

  7. 高度为5的3阶b树含有的关键字个数_第15期:索引设计(索引组织方式 B+ 树)

    谈到索引,大家并不陌生.索引本身是一种数据结构,存在的目的主要是为了缩短数据检索的时间,最大程度减少磁盘 IO. 任何有数据的场景几乎都有索引,比如手机通讯录.文件系统(ext4xfsntfs).数据 ...

  8. 【数据结构】_树与二叉树

    目录 引言 一.什么是树? 1.树的定义 2.树的特点 3.树的表示法 二.树的一些基本术语 三.树的性质 四.什么是二叉树? 1.基本概念 2.二叉树的五种基本形态 3.二叉树的性质 五.满二叉树. ...

  9. 编译原理学习笔记(二十九)~习题:分析句子 id--id*id的 最右推导过程,画出分析树,找出和分析过程中每一步的对应关系。

    题目 分析句子 id–id*id的 最右推导过程,画出分析树,找出和分析过程中每一步的对应关系. 语法如下: E → E - T (1) E → T (2) T → T * F (3) T → F(4 ...

最新文章

  1. python -- IO多路复用
  2. SpringBoot - 实践阿里巴巴【Manager 层_通用业务处理层】
  3. 我本人一直以来犯的错误,在看了 Think In Java 后才抓了出来
  4. dedecms 常用标签
  5. 用自定义函数联合IF函数实现“一对多”查询
  6. 拼多多开除即将拿到股票的安全大佬;虾米音乐将永久关停;GitHub 解禁伊朗开发者使用权
  7. h5球的立体效果_使用HTML5 Canvas 2D直角坐标系实现三维球体效果
  8. Linux 下 4 种实时监控日志文件的方法,你都会用吗?
  9. 同步手绘板——关于/dev/graphics/fb0权限的获取
  10. 卸载Symantec——无需密码,卸载干净,Windows
  11. html5禁用浏览器下拉,禁止ios浏览器页面上下滚动 (橡皮筋效果)
  12. C/C++之奔跑的小人(小游戏,自娱自乐)
  13. android读取wlan信息,Android判断Wlan信号强弱及wlan管理信息
  14. 分享一个优雅的vi配置
  15. [stanford NLP] 原理小结
  16. 入手评测 联想小新Pro16和thinkbook15p有什么区别 选哪个
  17. REST Assured 17 - 设置默认的RequestSpecification
  18. 系统信息:uname,sysinfo,gethostname,sysconf
  19. 【饭谈】软素质怎么提高?(适合软件测试人的专用办法)
  20. 转计算机网络应用申请书,转专业相关申请书最新6篇

热门文章

  1. [perl]字符串转拼音首字母(支持多音字)
  2. 二十、Java基础--------IO流之其他对象
  3. Input标签牲描述
  4. 生物信息学——RNA的剪切过程
  5. 【Pycharm IDE】修改字体大小/设置缩略图/设置高亮
  6. Android usb audio调用流程(二)
  7. odex vdex art区别
  8. Hls之TS流分离音视频
  9. 视频编解码(四):编辑器驱动移植步骤(VE)
  10. Educoder Basemap和Seaborn 第一关:Seaborn