何为LCA(最近共同祖先)?

news2024/11/26 18:43:04

原篇:(ACM算法)tarjan算法求LCA - 知乎 (zhihu.com)

顾名思义,就是求两个节点最近的共同祖先,就好比下图,2和3的共同祖先为3,2和4的共同祖先为1。

关于LCA求解有3种算法。

1.标记回溯法(也称暴力枚举,从一个点开始向上标记他的父节点,直接标记到根节点为止,然后另另一个点也开始向上回溯,当这个点被标记过,则找到这两个点的共同祖先),当数据过大时,很明显这个算法会超时,所以本文不过多解释此方法。

2.ST倍增法(本文也不重点介绍次方法,读者可看其他博客阅读此方法)

3.targan算法(本文重点介绍)

tarjan算法就这几个步骤:
1.标记当前节点x已访问,但是还没有回溯

2.枚举所有没有访问的过的子节点y,继续遍历子节点

3.合并y到x上

4.访问所有与当前节点有询问并且回溯过的y x,y的lca就是find(y)

5.标记当前节点回溯

首先targan是基于并查集实现的,没学过的读者可点击此传送门:何为并查集?-CSDN博客

具体过程看以下代码:

#include<bits/stdc++.h>
#define int long long 
#define endl "\n"
#define fi first
#define se second
#define PII pair<int,int> 
using namespace std;
const int N=5e5+5;
int fa[N],vis[N];
vector<int> v[N];
vector<PII> query[N];
int ans[N]; 
int find(int x){//并查集模板 
	if(fa[x]==x)  return x;
	else return fa[x]=find(fa[x]);
}
void tarjan(int x){
	vis[x]++;//第一次走过的路径标记为1 
	for(auto i :v[x]){
		if(!vis[i]){//若子节点没走过 继续遍历子节点 
		tarjan(i);
		fa[i]=x;//合并子节点到当前节点 
		}		
	}
	for(auto t : query[x]){
		int a=t.fi,b=t.se;
		if(vis[a]==2&&!ans[b]) ans[b]=find(a);// 若已经回溯并且b下标为空 
	}
	vis[x]++;//回溯的路径标记为2 
}
void solve(){	
	int n,m,q;
	cin >> n >> m >> q;
	for(int i=1;i<n;++i){
		int x,y;
		cin >> x >> y;
		v[x].push_back(y);//将x,y存入数组中 
		v[y].push_back(x);
	}
	for(int i=1;i<=n;++i) fa[i]=i;//预处理所有节点都是自己的父节点 
	for(int i=1;i<=m;++i){
		int x,y;
		cin >> x >> y;
		if(x==y){//特判 
			ans[i]=x;
			continue;
		}
		query[x].push_back({y,i});//存入查询的数字 
		query[y].push_back({x,i});
	}
	tarjan(q);
	for(int i=1;i<=m;++i){
		cout << ans[i] << endl;
	}
	return ;
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}

经典例题:P3884 [JLOI2009] 二叉树问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

解题思路:用层序遍历的思想求出树的深度和宽度,同时标记每个节点所在的层数,然后用tarjan算法求出a和b的共同祖先,最后套公式输出距离即可。

实现代码:

#include<bits/stdc++.h>
#define int long long 
#define endl "\n"
#define fi first
#define se second
#define PII pair<int,int> 
using namespace std;
const int N=105;
vector<int> v[N];
vector<int> s[N];
queue<PII> q;
int a,b;
int vis[N],fa[N],c[N];
vector<PII> query[N];
int ans1,ans2;
int k;
PII pa;
void check(int x){
	q.push({1,1});
	c[1]=1;
	int sum=0;
	int t=1;
	while(!q.empty()){
		pa=q.front();
		q.pop();
		if(pa.se==t) sum++;
		else{
			ans2=max(ans2,sum);
			t++;
			sum=1;
		}
		c[pa.fi]=pa.se;
		for(int i=0;i<s[pa.fi].size();++i){
			q.push({s[pa.fi][i],pa.se+1});
		}
	} 
	ans1=t;
	ans2=max(ans2,sum);
}
int find(int x){
	if(fa[x]==x)  return x;
	else return fa[x]=find(fa[x]);
}
void tarjan(int x){
	vis[x]++; 
	for(auto i :v[x]){
		if(!vis[i]){
		tarjan(i);
		fa[i]=x;
		}		
	}
	for(auto t : query[x]){
		int a=t.fi;
		if(vis[a]==2){
			k=find(a);
			break;
		} 
	}
	vis[x]++;
}
void solve(){
	int n;
	cin >> n;
	for(int i=1;i<n;++i){
		int x,y;
		cin >> x >> y;
		v[x].push_back(y);
		v[y].push_back(x);
		s[x].push_back(y);
	}	
	for(int i=1;i<=n;++i) fa[i]=i; 
	cin >> a >> b;
	query[a].push_back({b,1});
	query[b].push_back({a,1});
	check(1);
	cout << ans1 << endl << ans2 << endl;
	tarjan(1);
	//for(int i=1;i<=n;++i) cout << c[i] << endl; 
	cout << (c[a]-c[k])*2+(c[b]-c[k]);
	return ;
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	int t=1;
	//cin >> t;
	while(t--) solve();
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1671381.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024期从、证从、基从、银从备考资料及互助交流群

快进&#xff0c;2024年 金融考证备考资料及互助交流备考群&#xff0c;考啥进啥 5.12 &#xff08;基从&#xff09;基金从业资格考试 5.18&#xff08;期从&#xff09;期货从业资格考试 6.1 &#xff08;证从&#xff09;证券从业资格考试 6.1&#xff5e;6.2&#xff08;银…

MySQL从入门到高级 --- 6.函数

文章目录 第六章&#xff1a;6.函数6.1 聚合函数6.2 数学函数6.3 字符串函数6.4 日期函数6.4.1 日期格式 6.5 控制流函数6.5.1 if逻辑判断语句6.5.2 case when语句 6.6 窗口函数6.6.1 序号函数6.6.2 开窗聚合函数6.6.3 分布函数6.6.4 前后函数6.6.5 头尾函数6.6.6 其他函数6.7 …

Offer必备算法38_贪心算法四_八道力扣题详解(由易到难)

目录 ①力扣56. 合并区间 解析代码 ②力扣435. 无重叠区间 解析代码 ③力扣452. 用最少数量的箭引爆气球 解析代码 ④力扣397. 整数替换 解析代码1_递归改记忆化搜索 解析代码2_贪心策略 ⑤力扣354. 俄罗斯套娃信封问题 解析代码1_动态规划&#xff08;超时&#xf…

SAP-MM-BASIS-采购审批权限配置

如何控制某用户的审批权限? 例如: 公司人员变动,审批流从原来的经理审批、总监审批,现在要改成主管审批、经理审批。 1、权限变更 1.1、找到配置路径 以经理为例:SU01 点击查看/更改, 点击角色,找到审批文件,双击角色ZM0019_3000 上图可以控制采购订单的凭证类型和…

AVL树的完全指南:平衡与性能

文章目录 AVL树简介AVL的操作建立一个AVL树插入操作删除操作 书写代码1.构造函数和析构函数2.获取最大值和最小值3.树的高度和节点个数3.前序中序和后序遍历4.判断树是否为空树5.四个旋转操作6.获取平衡因子7.插入操作8.删除操作9.搜索节点.h文件中的定义 总结 AVL树简介 AVL树…

企业邮箱是什么?怎么申请一个企业邮箱

企业邮箱是什么&#xff1f;企业邮箱包含着许多企业需要的功能&#xff0c;包含统一创建签名、大容量存储、域名定制等功能&#xff0c;这些功能能够帮助企业更好地展示企业的专业形象以及更好得协作办公。本文将详细介绍企业邮箱的概念、特征和企业邮箱的申请步骤。 一、企业…

EasyExcel 中实体类的注解@ExcelProperty

ExcelProperty(value "职务", index 0) value 与index 的优先级, 实测得出下面结论. 1、只有value : 按照value 的匹配 2、只有index: 按照index 的匹配 3、 同时有value和index: 按照index的匹配. 结果: 按照index的匹配, 找到的数据 {"administrat…

Django 安全性与防御性编程:如何保护 Django Web 应用

title: Django 安全性与防御性编程&#xff1a;如何保护 Django Web 应用 date: 2024/5/13 20:26:58 updated: 2024/5/13 20:26:58 categories: 后端开发 tags: CSRFXSSSQLUploadHTTPOnlyPasswordSession 跨站请求伪造&#xff08;CSRF&#xff09; 跨站请求伪造&#xff0…

TriCore:Interrupt 2

今天继续来看看 IR 模块。 名词缩写 缩写全称说明IRInterrupt Router SRService Request 包括&#xff1a; 1. External Resource 2. Internal Resource 3.SW&#xff08;Software&#xff09; SPService Privoder 包括&#xff1a; 1. CPU 2. DMA SRNService Request NodeS…

宁夏银川最牛起名大师的老师颜廷利:宝与饱,饿跟恶

对于中国优秀传统文化之根-汉语而言&#xff0c; 恶&#xff0c;对应着‘饿’&#xff1b; 宝&#xff0c;对应着‘饱’… 由此可见&#xff0c;无论是‘饿’&#xff08;与‘恶’同音&#xff09;&#xff0c;还是‘饱’&#xff08;与‘宝’通音&#xff09;&#xff0c;实际…

GDPU unity游戏开发 角色控制器与射线检测

在你的生活中&#xff0c;你一直扮演着你的角色&#xff0c;别被谁控制了。 小试 1. 创建一个角色控制器&#xff0c;通过键盘控制角色控制器的移动&#xff0c;角色控制器与家具发生碰撞后&#xff0c;通过Debug语句打印出被碰撞物体的信息(搜索OnControllerColliderHit的使用…

GO语言核心30讲 实战与应用 (WaitGroup和Once,context,Pool,Map,字符编码,string包,bytes包)

原站地址&#xff1a;Go语言核心36讲_Golang_Go语言-极客时间 一、sync.WaitGroup和sync.Once 1. sync.WaitGroup 比通道更加适合实现一对多的 goroutine 协作流程。 2. WaitGroup类型有三个指针方法&#xff1a;Wait、Add和Done&#xff0c;以及内部有一个计数器。 (1) Wa…

【报错合集】完美解决“虚拟机使用的是此版本 VMware Workstation 不支持的硬件版本”

文章目录 解决方案&#xff1a;更改设置的硬件版本 今天我需要将别人的虚拟机克隆到我的VMware Workstation上运行&#xff0c;结果发生了以下的错误&#xff1a; 刚开始以为是VMware Workstation的版本问题太低导致的&#xff0c;所以我删除了原来的那个版本&#xff0c;下载…

51cto已购买的视频怎么下载到本地

你是否曾在学习51CTO的精品课程时&#xff0c;希望可以随时随地无网络干扰地进行学习&#xff0c;或是想要将这些已购买的课程永久珍藏&#xff1f;今天&#xff0c;你的愿望将要实现。我们将向你揭示如何轻松地将已购买的51CTO视频下载到本地&#xff0c;让学习的路上再也没有…

企业邮箱域名是什么?怎么注册一个企业邮箱域名?

企业邮箱域名是什么&#xff1f;企业邮箱域名是企业申请的专属域名&#xff0c;绑定专属的邮箱域名&#xff0c;能够在发送邮件时提高品牌识别性、专业性和宣传效果。那么&#xff0c;我们该怎么注册一个企业邮箱域名呢&#xff1f;本文将为你详细介绍。 一、企业邮箱域名是什…

本地搭建各大直播平台录屏服务结合内网穿透工具实现远程管理录屏任务

文章目录 1. Bililive-go与套件下载1.1 获取ffmpeg1.2 获取Bililive-go1.3 配置套件 2. 本地运行测试3. 录屏设置演示4. 内网穿透工具下载安装5. 配置Bililive-go公网地址6. 配置固定公网地址 本文主要介绍如何在Windows系统电脑本地部署直播录屏利器Bililive-go&#xff0c;并…

内网环境安装使用DBeaver使用第一天

之前一直使用navicat&#xff0c;现在出于某种原因不让使用了&#xff0c;于是上手了这个工具&#xff0c;说实话&#xff0c;真的&#xff0c;但是必须要用。 首先安装的时候&#xff0c;必须要选择MySQL驱动&#xff0c;如果外网直接选择以后就可以下载了&#xff0c;内网需…

【MySQL复合查询】

文章目录 一、基本的使用案例二、多表查询三、自连接四、子查询4.1单行子查询4.2多行子查询in关键字all关键字any关键字 4.3多列子查询4.4 在from子句中使用子查询 解决多表问题的本质五、合并查询1.union2.union all 一、基本的使用案例 注明&#xff1a;以下案例使用的均为一…

Docker-compose部署TRX节点

1、编写Dockerfile rootubuntu:~# mkdir /data/docker-compose/trx -p rootubuntu:~# cd /data/docker-compose/trx/ rootubuntu:/data/docker-compose/trx# ls rootubuntu:/data/docker-compose/trx# vim Dockerfile rootubuntu:/data/docker-compose/trx# cat Dockerfile FR…

鲁棒控制问题描述

复杂的合成问题成为一个具有特殊结构控制器的设计问题。 H无穷范数&#xff08;H∞ norm&#xff09;&#xff1a;对于线性时不变&#xff08;LTI&#xff09;系统&#xff0c;H∞范数通常定义为系统频率响应的最大幅值。换句话说&#xff0c;它是系统传递函数在复平面单位圆上…