lca入门

目录

  1. 一:定义
  2. 二:实现
    1. 壹:暴力
      1. 1.标记法
      2. 2.跳跃法(1)
      3. 3.跳跃法(2)
      4. 4.注意
    2. 贰:倍增法
  3. 三:结语

一:定义

OI Kiki上是这么说的

最近公共祖先简称 LCA(Lowest Common Ancestor)。两个节点的最近公共祖先,就是这两个点的公共祖先里面,离根最远的那个(也就是离两个点最近的那个)

二:实现

壹:暴力

1.标记法

可以先让一个点一直往上跳到根节点,然后每次给跳到的点打上标记(初始点要打)

最后从另一个点也往上跳,如果这个点有标记就输出

2.跳跃法(1)

每次让深度比较大的那个点向上跳,如果两个点相遇了,就输出

3.跳跃法(2)

先让深度较大的点一直跳到与另一个点深度相同,然后再共同向上跳,如果两个点重回,就输出

4.注意

两个跳跃法都需要先预处理出深度

贰:倍增法

大家可以先看看我的这篇博客学习一下RMQ,这里也是用差不多的方法

我们现设ans[i][j]表示从i点往上走2^{j}步走到的点

那么ans[i][j] = ans[ans[i][j-1][j-1]

ans[i][0]就等于i的父亲节点

接着,我们可以运用我之前讲的跳跃法(2)来进行寻找,最后输出就行了

这里放上代码

vector<int> a[114514];//作者这里使用vector来存树
int b[114514];//每个点的深度
inn ans[114514][22];//跳跃到点
void dfs(int x,int fa,int sum){//用来求深度(根节点的深度为一)
    b[x] = sum;
    for(int i=0;i<a[x].size();i++){
    	int y = a[x][i];
		if(y==fa) continue;
        ans[y][0] = x;
		dfs(y,x,sum+1);
	}
}
int lca(int x,int y){//跳跃法
	if(b[x]<b[y]) swap(x,y);//找出深度小的点
	for(int i=20;i>=0;i--) if(b[ans[x][i]]>=b[y]) x = ans[x][i];//不断进行调整
	if(x==y) return x;//如果两个点在同一个点了(原本在一颗子树)就输出
	for(int i=20;i>=0;i--) if(ans[x][i]!=ans[y][i]) x = ans[x][i],y = ans[y][i];//同步进行跳跃
	return ans[x][0];//最后输出
}

三:结语

如果这篇文章对您有帮助的话,请记得点赞收藏加关注吖~

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值