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

原篇:(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.hqwc.cn/news/696877.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STK12 RPO模块学习 (1)

一、背景介绍 在STK12中&#xff0c;在Astrogator的模块上开发了新的模块&#xff08;Rendezvous and proximity operations)。轨道交会接近通常来说是一个很复杂的过程。RPO实现需要对轨道动力学有一个清晰的理解&#xff0c;并且对于Astrogator模块具备很强的背景和经验&…

7B2 PRO主题5.4.2 免授权开心版源码 | WordPress主题

简介&#xff1a; B2 PRO 5.4.2 最新免授权版不再需要改hosts&#xff0c;和正版一样上传安装就可以激活。 直接在WordPress上传安装即可 点击下载

Git详解之六:Git工具

现在&#xff0c;你已经学习了管理或者维护 Git 仓库&#xff0c;实现代码控制所需的大多数日常命令和工作流程。你已经完成了跟踪和提交文件的基本任务&#xff0c;并且发挥了暂存区和轻量级的特性分支及合并的威力。 接下来你将领略到一些 Git 可以实现的非常强大的功能&…

Ubuntu安装VScode

Ubuntu安装VScode 前言&#xff1a; 1、Ubuntu安装VScode比较方便 2、我更喜欢source insight 1、获取到linux版本的VScode安装包 VSCode 下载地址是&#xff1a;https://code.visualstudio.com/ 2、得到安装包 3、复制到ubuntu中&#xff0c;使用命令安装 sudo dpkg -i cod…

idea 使用 git

可以看见项目地址&#xff0c; git clone 地址 就可以拉新项目了 命令 git remote -v

数字工厂管理系统如何助力企业数据采集与分析

随着科技的不断进步&#xff0c;数字化已成为企业发展的重要趋势。在制造业领域&#xff0c;数字工厂管理系统的应用日益广泛&#xff0c;它不仅提升了生产效率&#xff0c;更在数据采集与分析方面发挥着举足轻重的作用。本文旨在探讨数字工厂管理系统如何助力企业数据采集与分…

STM32(开篇总结)

STM32介绍 STM32是意法半导体公司基于ARM Cortex-M内核开发的32位微控制器 STM32常应用在嵌入式领域&#xff0c;如智能车、无人机、机器人、无线通信、物联网、工业控制、娱乐电子产品等 STM32功能强大、性能优异片上资源丰富、功耗低&#xff0c;是一款经典的嵌入式微控制器…

提升文本到图像模型的空间一致性:SPRIGHT数据集与训练技术的新进展

当前的T2I模型&#xff0c;如Stable Diffusion和DALL-E&#xff0c;虽然在生成高分辨率、逼真图像方面取得了成功&#xff0c;但在空间一致性方面存在不足。这些模型往往无法精确地按照文本提示中描述的空间关系来生成图像。为了解决这一问题&#xff0c;研究人员进行了深入分析…

Web APIs(获取元素+操作元素+节点操作)

目录 1.API 和 Web API 2.DOM导读 DOM树 3.获取元素 getElementById获取元素 getElementsByTagName获取元素 H5新增方法获取 获取特殊元素 4.事件基础 执行事件 操作元素 修改表单属性 修改样式属性 使用className修改样式属性 获取属性的值 设置属性的值 移除…

宁夏银川市起名专家的老师颜廷利:死神(死亡)并不可怕,可怕的是...

在中国优秀传统文化之中&#xff0c;汉语‘巳’字与‘四’同音&#xff0c;在阿拉伯数字里面&#xff0c;通常用‘4’来表示&#xff1b; 湖南长沙、四川成都、重庆、宁夏银川最靠谱最厉害的起名大师的老师颜廷利教授指出&#xff0c;作为汉语‘九’字&#xff0c;倘若是换一个…

FPGA OSD 方案,应用于XBOX游戏机收费等领域

FPGA方案&#xff0c;HDMI IN接收原始HDMI 信号&#xff0c;HDMI OUT输出叠加字符/图片后的HDMI信号 客户应用&#xff1a;XBOX游戏机收费 主要特性&#xff1a; 1.支持多分辨率格式显示 2.支持OSD 叠加多个图层 3.支持字体大小随意配置 4.支持字体格式随意配置 5.零延时&…

【知识碎片】2024_05_13

本文记录了两道代码题【自除数】和【除自身以外数组的乘积】&#xff08;利用了前缀积和后缀积&#xff0c;值得再看&#xff09;&#xff0c;第二部分记录了关于指针数组和逗号表达式的两道选择题。 每日代码 自除数 . - 力扣&#xff08;LeetCode&#xff09; /*** Note: T…