浅谈LCA(最近公共祖先)

#简介

首先是最近公共祖先的概念(什么是最近公共祖先?):
在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点。
换句话说,就是两个点在这棵树上距离最近的公共祖先节点。
所以LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径。

#讲解
我们今天介绍一种计算LCA的方法——Tarjan。
Tarjan算法是一种离线的操作。它可以实现一次性用O(nm)的时间(m是询问的个数)算出所有询问的LCA。
Tarjan算法大概流程有三个步骤:

  1. 搜索子节点,直到无法延伸下去为止。
  2. 查找询问,即所有与它有关系的点,如果它也被访问过,就可以直接寻找。
  3. 查询完毕,与父亲合并,返回。
    程序的流程大概是这样的:
void Tarjan(int t)
{
	int i=last[t],yy=0;
	bz[t]=true;
	while (i)
	{
		yy=tov[i];
		if (bz[yy]==false)
		{
			Tarjan(yy);
			father[yy]=t;//合并父亲结点
		}
		i=next[i];
	}
	for (i=1;i<=与t有关系的点的个数;++i)
	{
			设这个数为x;
			LCA(t,x)=find(x);
	}
}

这样可能还是不太明白,那我在这里举一个模拟的例子。
这里写图片描述
我们从根结点开始搜索:
这里写图片描述
这样操作完整棵树,然后就可以把所有的操作都算完…

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值