【模板】倍增求LCA
题目链接
一、 时间戳法(本质上是dfs序)
#include<cstdio>
using namespace std;
const int NN = 5e5+8;
int n,m,s;
int tin[NN],tout[NN],timetable;
int fa[NN][30];
struct Edge{
int next,to;
}edge[NN<<1];
int head[NN],cnt;
void init(){
cnt = 1;
for(int i = 1; i <= n; i++)head[i] = -1;
}
void add_edge(int u,int v){
edge[++cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt;
}//链式前向星
void dfs(int now,int father){
fa[now][0]=father;
tin[now] = ++timetable;
for(int j = 1; j <= 29 ; j++){
fa[now][j] = fa[fa[now][j-1]][j-1];
}
for(int i = head[now]; i != -1; i = edge[i].next){
int tt = edge[i].to;
if(father != tt)dfs(tt,now);
}
tout[now] = ++timetable;
return;
}//一遍dfs预处理fa数组,时间戳
bool isfather(int a,int b){
return tin[a]<tin[b]&&tout[b]<tout[a];
}//可以知道先进入dfs后退出的一定是更先搜到
int LCA(int x,int y){
if(x==y)return x;
if(isfather(x,y))return x;
if(isfather(y,x))return y;
int now = x;
for(int i = 29; i >= 0; i--){
if(!isfather(fa[now][i],y))now = fa[now][i];
}
return fa[now][0];
}
int main(){
scanf("%d%d%d",&n,&m,&s);
init();
for(int i = 1,u,v; i < n; i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(s,s);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",LCA(u,v));
}
return 0;
}
码量:1228

二、 普通法(先跳到同一深度,再向上跳)
#include<cstdio>
#include<algorithm>
using namespace std;
const int NN = 5e5+8;
int n,m,s;
int fa[NN][30],dep[NN];
struct Edge{
int next,to;
}edge[NN<<1];
int head[NN],cnt;
void init(){
cnt = 1;
for(int i = 1; i <= n; i++)head[i] = -1;
}
void add_edge(int u,int v){
edge[++cnt].next = head[u];
edge[cnt].to = v;
head[u] = cnt;
}//链式前向星
void dfs(int depth,int now,int father){
fa[now][0] = father;
dep[now] = depth;
for(int i = 1; i <= 29; i++){
fa[now][i] = fa[fa[now][i-1]][i-1];
}
for(int i = head[now]; i != -1; i = edge[i].next){
int tt = edge[i].to;
if(tt != father)dfs(depth+1,tt,now);
}
}//一遍dfs处理fa数组
int LCA(int x,int y){
if(dep[y]>dep[x])swap(x,y);
int t = dep[x]-dep[y];
for(int i = 0; t; i++){
if(t&1)x = fa[x][i];
t>>=1;
}//跳到同一深度
if(x==y)return x;
for(int i = 29; i >= 0; i--){
if(fa[x][i] != fa[y][i])x = fa[x][i],y = fa[y][i];
} //倍增
return fa[x][0];
}
int main(){
scanf("%d%d%d",&n,&m,&s);
init();
for(int i = 1,u,v; i < n; i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(1,s,s);
while(m--){
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",LCA(u,v));
}
return 0;
}
码量:1179

两种代码自取
【模板】倍增求LCA的更多相关文章
- [算法模板]倍增求LCA
倍增LCA \(fa[a][i]\)代表a的第\(2^{i}\)个祖先. 主体思路是枚举二进制位,让两个查询节点跳到同一高度然后再向上跳相同高度找LCA. int fa[N][21], dep[N]; ...
- 倍增求lca模板
倍增求lca模板 https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> ...
- 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))
倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- 【倍增】洛谷P3379 倍增求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- hdu 2586 How far away ? 倍增求LCA
倍增求LCA LCA函数返回(u,v)两点的最近公共祖先 #include <bits/stdc++.h> using namespace std; *; struct node { in ...
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- 树链剖分与倍增求LCA
树链剖分与倍增求\(LCA\) 首先我要吐槽机房的辣基供电情况,我之前写了一上午,马上就要完成的时候突然停电,然后\(GG\)成了送链剖分 其次,我没歧视\(tarjan LCA\) 1.倍增求\(L ...
- [学习笔记] 树上倍增求LCA
倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...
随机推荐
- Dive into TensorFlow系列(1)-静态图运行原理
接触过TensorFlow v1的朋友都知道,训练一个TF模型有三个步骤:定义输入和模型结构,创建tf.Session实例sess,执行sess.run()启动训练.不管是因为历史遗留代码或是团队保守 ...
- MindSpore Graph Learning
技术背景 MindSpore Graph Learning是一个基于MindSpore的高效易用的图学习框架.得益于MindSpore的图算融合能力,MindSpore Graph Learning能 ...
- 微信小程序的学习(一)
一.小程序简介 1.小程序与普通网页开发的区别 运行环境不同 网页运行在浏览器环境中 小程序运行在微信环境中 API不同 小程序无法调用浏览器中的DOM和BOM的API 但是小程序可以调用微信环境提供 ...
- 面试 考察js基础不能不会的内容(第五天)
01.描述事件冒泡的流程 基于 DOM 树结构,事件会顺着触发元素向上冒泡 点击一个div,会一级一级向父级.爷级元素上冒泡,这个点击事件不仅能被这个div捕捉到,也能被他的父级.爷爷级-元素捕捉到 ...
- (GDB) GDB调试技巧,调试命令
调试时查看依赖DSO pidof tvm_rpc_server cat /proc/<pid_of_tvm_rpc_server>/maps 子进程调试 1.vscode -- launc ...
- 前端项目通过‘URL 重写’部署在 IIS 中,访问 WebAPI 接口
〇.前言 在前端项目开发时,我们可以通过配置代理 proxy 来访问本地或者是远程接口,但是部署后代理就失效了.如果项目部署在 IIS 上,就没法去对应到指定接口,此时就需要 IIS 中的'URL重写 ...
- python-CSV文件的读写
CSV文件:Comma-Separated Values,中文叫逗号分隔值或者字符分隔值,其文件以纯文本的形式存储表格数据. 可以理解成一个表格,只不过这个 表格是以纯文本的形式显示,单元格与单元格之 ...
- 1分钟理清楚C++类模板和模板类区别
1.定义区别 类模板和模板类主要关注点是后一个单词. 类模板:主要描述的是模板,这个模板是类的模板.可以理解为一个通用的类,这个类中的数据成员,成员函数的形参类型以及成员函数的返回值类型不用具体的指定 ...
- Django框架:2、静态文件配置、form表单、request对象、pycharm链接数据库、django链接数据库、ORM框架
Django框架 目录 Django框架 一.静态文件配置 1.静态文件 2.配置方法 二.form表单 1.action属性 2.method属性 三.request对象 1.基本用法 四.pych ...
- 三个小任务掌握List、Set、Map
任务一: ArrayList.Vector 和 LinkedList 都实现了 List 接口,对它们分别进行如下操作后比 较它们的不同,然后形成初步耗时报告(三种不同 List 的耗时): 追加元素 ...