洛谷P3379 【模板】最近公共祖先(LCA)
洛谷P3379 【模板】最近公共祖先(LCA)
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
5 5 4 3 1 2 4 5 1 1 4 2 4 3 2 3 5 1 2 4 5
4 4 1 4 4
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
样例说明:
该树结构如下:
第一次询问:2、4的最近公共祖先,故为4。
第二次询问:3、2的最近公共祖先,故为4。
第三次询问:3、5的最近公共祖先,故为1。
第四次询问:1、2的最近公共祖先,故为4。
第五次询问:4、5的最近公共祖先,故为4。
故输出依次为4、4、1、4、4。
代码
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=500000+5; inline int read() {int x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}return x*f; } int n,m,s,num; int f[maxn][30],head[maxn],dep[maxn]; bool vis[maxn]; struct node {int next,to; }e[maxn<<1]; inline void add(int from,int to) {e[++num].next=head[from];e[num].to=to;head[from]=num; } inline void dfs(int x,int d) {vis[x]=1;dep[x]=d;for(int i=head[x];i;i=e[i].next){int to=e[i].to;if(!vis[to]){f[to][0]=x;dfs(to,d+1);}} } inline int lca(int a,int b) {if(dep[a]<dep[b]){int t=a;a=b;b=t;}int d=dep[a]-dep[b];for(int i=20;i>=0;i--)if(d&(1<<i)) a=f[a][i];if(a==b) return a;for(int i=20;i>=0;i--)if(f[a][i]!=f[b][i]){a=f[a][i];b=f[b][i];}return f[a][0]; } int main() {n=read();m=read();s=read();for(int i=1;i<n;i++){int x,y;x=read();y=read();add(x,y);add(y,x);}dfs(s,1);for(int j=1;j<=20;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];for(int i=1;i<=m;i++){int a,b,ans;a=read();b=read();ans=lca(a,b);printf("%d\n",ans);}return 0; }
树上倍增
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=500000+5; inline int read() {int x=0,f=1; char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-')f=-1; ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}return x*f; } int n,m,s,num,qnum; int father[maxn],head[maxn],qhead[maxn],a[maxn][3]; bool vis[maxn]; struct node {int next,to; }e[maxn<<1]; struct qnode {int next,to,k; }q[maxn<<1]; inline void add(int from,int to) {e[++num].next=head[from];e[num].to=to;head[from]=num; } inline void qadd(int from,int to,int k) {q[++qnum].next=qhead[from];q[qnum].to=to;q[qnum].k=k;qhead[from]=qnum; } inline int find(int x) {if(x!=father[x]) father[x]=find(father[x]);return father[x]; } inline void merge(int x,int y) {int r1=find(x);int r2=find(y);father[r1]=r2; } void tarjan(int x) {vis[x]=1;for(int i=qhead[x];i;i=q[i].next){int to=q[i].to,k=q[i].k;if(vis[to]) a[k][2]=find(to);}for(int i=head[x];i;i=e[i].next){int to=e[i].to;if(!vis[to]){tarjan(to);merge(to,x);}} } int main() {n=read();m=read();s=read();for(int i=1;i<=n;i++) father[i]=i;for(int i=1;i<n;i++){int x,y;x=read();y=read();add(x,y);add(y,x);}for(int i=1;i<=m;i++){a[i][0]=read();a[i][1]=read();qadd(a[i][0],a[i][1],i); qadd(a[i][1],a[i][0],i);}tarjan(s);for(int i=1;i<=m;i++)printf("%d\n",a[i][2]);return 0; }
tarjan算法
转载于:https://www.cnblogs.com/huihao/p/7793221.html
洛谷P3379 【模板】最近公共祖先(LCA)相关推荐
- 最近公共祖先(LCA)
最近公共祖先 向上标记法 树上倍增 Tarjan发明的算法 转化为求区间最小值问题 最近公共祖先问题是树中的常考问题,比如我们有一棵树(可以是多叉的),两个点的最近公共祖先就是字面的意思,比如说6.5 ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)...
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- 【C++】最近公共祖先 LCA
最近公共祖先 百科名片 简单引入 LCA的算法 暴力枚举法 Tarjan离线算法 倍增算法 例题: 题目描述 输入描述 输出描述 样例输入 样例输出 代码 百科名片 最近公共祖先 Lowest Com ...
- 最近公共祖先 (LCA) [No. 21]
问题: 给定一个二叉树,找到两个节点NA, NB的最近公共祖先(LCA). 比如对于下图,4 和 7 的 LCA 是6, 1和13的LCA 是 8. 我们这里先考虑一般的二叉树(BT),然后再考虑这个 ...
- 树上倍增法求最近公共祖先LCA
LCA,最近公共祖先,这个东西有很多作用,因此,如何高效求出LCA就成了一个热点的讨论话题. 下面所有的讨论都以图中这棵树为例子. 先来了解下什么是倍增吧,倍增其实就是二分的逆向,二分是逐渐缩小范围, ...
- 图论--最近公共祖先LCA
最近公共祖先LCA LCA(Least Common Ancestors),即最近公共祖先,是指这样一个问题:在有根树中,找出某两个结点u和v最近的公共祖先(另一种说法,离树根最远的公共祖先) 最近公 ...
- 洛谷·【模板】点分树 | 震波【including 点分树
初见安-这里是传送门:洛谷P6329 [模板]点分树 | 震波 一.点分树 其实你会点分治的话,点分树就是把点分治时的重心提出来重新连城一棵树. 比如当前点是u,求出子树v的重心root后将root与 ...
- 最近公共祖先LCA 【专题@AbandonZHANG】
参考: <算法艺术与信息学竞赛> --- 刘汝佳 博客:http://blog.163.com/kevinlee_2010/blog/static/16982082020120794613 ...
- 专题·树链剖分【including 洛谷·【模板】树链剖分
初见安~~~终于学会了树剖~~~ [兴奋]当初机房的大佬在学树剖的时候我反复强调过:"学树剖没有前途的!!!" 恩.真香. 一.重链与重儿子 所谓树剖--树链剖分,就是赋予一个链的 ...
最新文章
- 如何限制IP,通过SSH登陆linux服务器
- RabbitMQ指南(中)
- Python之tkinter:动态演示调用python库的tkinter带你进入GUI世界(计算器简单功能)
- CentOS7安装wdCP面板,快速搭建web运行环境(图文详解)
- 【收藏】docker的privileged 与 k8s的privileged 设置方式
- HTML5协议的,HTML5新增协议:WebSocket协议的实例
- Visual studio 打包
- Python的Pexpect详解 [图片]
- 紧急预警:wls9_async_response.war组件漏洞的延续
- linq判断集合中相同元素个数_java----Collection集合常用方法
- 软件质量管理体系 type:pdf_制造型企业构建完整的质量管理体系的思路要点
- bash脚本编程之十 函数
- sql智能语法提示插件 sql prompt 10
- Win系统新建文件夹快捷键
- 初学Java,搭建Java环境以及创建Java程序
- matlab函数power,Matlab中Powergui介绍.pdf
- 多智能体强化学习Multi agent,多任务强化学习Multi task以及多智能体多任务强化学习Multi agent Multi task概述
- 将网站放到桌面快捷方式
- 个人永久性免费-Excel催化剂功能第105波-批量调整不规范的图形对象到单一单元格内存储...
- 知识蒸馏——pytorch实现
热门文章
- sencha touch 入门学习资料大全
- OpenResty(nginx)操作redis的初步应用
- 苹果手机计算机键盘声音怎么办,苹果键盘声音怎么设置大小声
- 华为鸿蒙宣传悟空视频_给华为“鸿蒙”打Call,家居头条号探讨短片《悟空》获50万阅读...
- um是代表什么意思_白玫瑰代表什么意思 居然有这么多含义
- 信息系统项目的应急预案方案_从环评到验收、排污许可证、应急预案,都应在项目什么阶段开展? 先后顺序是什么?...
- 备战2020年双十一,刷喵币靠这一个自动化脚本就够了!
- 测试面试题集-MySQL数据库灵魂拷问
- 借贷平台Liquity昨日共有超300个Troves被清算
- NFT平台 NFTb将推出新版本,支持社会公益事业