首页 > 其他分享 >tarjan之LCA学习笔记

tarjan之LCA学习笔记

时间:2024-08-18 14:04:20浏览次数:12  
标签:tarjan 遍历 int 笔记 查询 yy LCA 节点

tarjan 之 LCA 学习笔记

tarjan算法求LCA可谓是一个极其巧妙的离线算法

其本质是利用 DFS 遍历时产生的 DFS 序 和 并查集 来在线性的时间复杂度内求出所有询问的结果

既然是离线算法,其和在线算法的区别就在与离线算法需要记录下所有查询,对查询进行一定操作来得到更高的效率 ,而这种操做往往是排序之类的

Tarjan求LCA 也是如此

先把所有询问离线下来,将询问的信息存在询问的两个节点上

首先,在树上的两个节点 \(x\) , \(y\) 只可能有两种关系(此处假定y的深度比x深)
1.\(y\) 在 \(x\) 的子树上
2.\(y\) 不在 \(x\) 的子树上

对于第一种关系,我们能很容易看出 \(x\) 就是要求的最近公共祖先
在 DFS 时,从 \(x\) 进入这一棵子树,毫无疑问的会遍历到 \(y\) 并将其打上标记
当回溯到 \(x\) 时若 \(y\) 已经打了标记,显然 \(x\) 就是要求的 LCA

对于第二种关系,我们假设 \(x\) 和 \(y\) 的 LCA 是 \(c\)
当我们从 \(c\) 进入子树后 \(x\) 和 \(y\) 中一定会有一个先被遍历到
在遍历到 \(x\) \(y\) 中的另一个点时,若对方已被标记,则 \(x\) 与 \(y\) 共同所在的这颗子树的根就是 LCA
所以,现在问题来了,我们怎么求 \(c\) 点呢?

Tarjan 发现,这个问题可以用并查集来解决

在 DFS 回溯的过程中 将一个节点在的父节点记为他在并查集中的父节点

随着逐级的回溯,\(y\) 点在并查集中的父节点会逐步上升直到 根节点

而当其在并查集中的父节点 上升到 \(c\) ,也就是 在 \(c\) 点遍历完了 \(y\) 所在的 \(c\) 点的子树后,还会 继续遍历 \(c\) 点的其他儿子及其子树,也就会遍历到 \(x\) 点 当遍历到 \(x\) 时,再查找 \(x\) 存储的查询 找到与 \(y\) 点有关的查询时,会发现 \(y\) 点被访问过
那么这个查询的答案也就是 LCA 就是 \(y\) 点在并查集中的父节点

好了,问题就这样解决了。。。吗?

当 \(x\) 查找查询时若 \(y\) 点还没被访问,也就是 \(x\) 点比 \(y\) 点先被访问怎么办?
没事,因为这个查询再 \(x\) 和 \(y\) 上都存了一遍,所以 当遍历到 \(y\) 时还是能得到查询的答案(你可以理解为将 \(x\) 和 \(y\) 对应的点互换了(相对之前的情况) )

还有复杂度的分析
首先,每个节点都被遍历了一遍 复杂度 O(n)
而每个查询 被其查找的两个节点 各遍历一次再加上并查集 复杂度 \(O(m*\alpha (m+n,n) + n)\)
所以总复杂度 \(O(m*\alpha (m+n,n) + n)\) 约等于 \(O(m + n)\)

这下真正结束了

上代码!

#include<bits/stdc++.h>
using namespace std;
struct node 
{
	vector<int> son;
	//int fa;
	bool vis;
	vector<pair<int,int > > query;//存与这个点有关的查询 first 是 查找的另一个点 second 是查询的编号 
};
node nodes[600000];
int fa[600000]; 

int ans[600000];//得出查询的答案 
int n,m,r;//r==root
int fnd(int x)//路径压缩并查集 
{
	if(fa[x]==x)
	{
		return x;
	}
	fa[x]=fnd(fa[x]);
	return fa[x];
}
void tarbuild(int now_)
{
	nodes[now_].vis=1;//标记这个节点已被访问过 
	int to_;
	for(int yy=0;yy<nodes[now_].son.size();yy++)//遍历所有儿子节点(此时没有管父节点是因为父节点已被访问过) 
	{
		to_=nodes[now_].son[yy]; 
		if(nodes[to_].vis==0)//若此儿子节点没有被访问过 
		{
			tarbuild(to_);//递归 
			fa[to_]=now_;//回溯 
		}
	}
	for(int yy=0;yy<nodes[now_].query.size();yy++)//查找所有查询 
	{
		int num_=nodes[now_].query[yy].second;
		int nod=nodes[now_].query[yy].first;
		if(nodes[nod].vis)//若被访问过 
		{
			ans[num_]=fnd(nod);//得出查询结果 
		}
	}
}
int main()
{
	ios::sync_with_stdio(0);
	cin>>n>>m>>r;
	for(int yy=1;yy<=n;yy++)
	{
		fa[yy]=yy;
	}
	int a,b;
	for(int yy=1;yy<n;yy++)
	{
		cin>>a>>b;
		nodes[a].son.push_back(b);
		nodes[b].son.push_back(a);
			
	}
	for(int yy=1;yy<=m;yy++)
	{
		cin>>a>>b;
		nodes[a].query.push_back({b,yy});//存查寻 
		nodes[b].query.push_back({a,yy});//两个点都要存一次 
	}
		
	tarbuild(r);//tarjan 
	for(int yy=1;yy<=m;yy++)
	{
		cout<<ans[yy]<<"\n";
	}
	return 0;
 } 


标签:tarjan,遍历,int,笔记,查询,yy,LCA,节点
From: https://www.cnblogs.com/sea-and-sky/p/18365590

相关文章

  • 【防忘笔记】Spring+Struts2古董框架学习
    Spring+Struts2项目框架梳理若基于Spring+Struts2的方式进行开发,前后端的交互逻辑会与boot系以及MCV的组织结构有所不同这里是对于学习过程的一些记录前置通用知识Struts2框架资料Struts2基础篇之基本概念Java之struts2框架学习一般情况的Spring前后端调试流程要理解基于......
  • ssy中学暑假集训有关数学及多项式学习笔记
    8.16日集训倒数第\(7\)天唉,不知不觉间在ssy中学的暑假集训就要结束了,只剩下一周的时间了,然而byn和yzh还有bao学姐\(21\)号就要走了,暑假就要过去了....今天模拟赛的第二题很有意思,涉及到了许多的数学知识,正好来恶补一下:浅谈反演原理和二项式反演首先来说说什么是反演(inversio......
  • FFmpeg开发笔记(四十八)从0开始搭建直播系统的开源软件架构
    ​音视频技术的一个主要用途是直播,包括电视直播、电脑直播、手机直播等等,甚至在线课堂、在线问诊、安防监控等应用都属于直播系统的范畴。由于直播系统不仅涉及到音视频数据的编解码,还涉及到音视频数据的实时传输,因此直播领域采用的网络技术标准比较高,实现起来也比一般的WEB系统复......
  • java基础概念笔记
    java基础概念1.注释分类单行注释://注释信息多行注释:/*注释信息*/文档注释:/**注释信息*/但是一般不用2.关键字2.1关键字的特点关键字的字母全部小写常用的代码编辑器,针对关键字有特殊的颜色标记,非常直观。注意:关键字很多,不用刻意去记。abstracta......
  • WebRTC音视频开发读书笔记(一)
    一、基本概念WebRTC(WebReal-TimeCommunication,网页即时通信)于2011年6月1日开源,并被纳入万维网联盟的W3C推荐标准,它通过简单API为浏览器和移动应用提供实时通信RTC功能。1、特点跨平台:可以在Web,Android、IOS、Windows、MacOS、Linux环境运行。实时传输:速度快、延迟低。......
  • 数学 做题笔记
    在这个随笔中,会有笔者的一些做题笔记,包括但不限于数学的思想、解题技巧、代码实现等。CF1361BJohnnyandGrandmasterTAG:数学,贪心,暴力思路:从最大的数开始枚举,如果当前为是偶数,差不变。如果当前为是奇数,则往下找,知道这个\(p^k\)被补齐。如果补齐不了,则后面的数一直往小的加......
  • 24/8/18算法笔记 MBPO算法
    MBPO(Model-BasedPolicyOptimization)是一种先进的强化学习算法,它结合了模型预测和策略优化的思想来提高学习效率和性能。这种算法特别适用于连续动作空间的问题,它通过建立一个环境的动态模型来进行模拟预测,并利用这些预测来改进策略。MBPO的核心包括以下几个步骤:模型学习:通......
  • [学习笔记]Python学习3——变量
                    上一篇笔记对Python环境进行了简介,了解了其组成以及相关概念。        公众号端:[学习笔记]Python学习2——Python环境https://mp.weixin.qq.com/s?__biz=MzkwMjc0MTE3Mw==&mid=2247483706&idx=1&sn=b0904c6b019c0a010fd85ab992efc......
  • DataWhale AI夏令营-大模型微调-学习笔记3
     Task1:从零入门大模型微调一、问题概述从零入门大模型微调是Datawhale2024年AI夏令营第四期的学习活动(“大模型技术”方向),基于讯飞开放平台“星火大模型驱动阅读理解题库构建挑战赛”开展的实践学习。学习内容:基于讯飞大模型定制训练平台和spark-13b微调模型,生成高考......
  • “Datawhale X 魔搭 AI夏令营“ AIGC 学习笔记 Task3(优化)
    认识ComfyUICpmfyUI主要用于让生成和调整AI图像的过程变得更加直观和容易。它允许用户通过图形界面来控制文本到图像的生成过程中的各种参数。ComfyUI核心及图片生成流程ComfyUI核心模块由模型加载器、提示词管理器、采样器、解码器。本小节内容来自魔搭社区,具体内容可点......