倍增求LCA(最近公共祖先)
题目描述:
读入一棵以1为根的树,q次询问,每次给定x和y,问x和y的最近公共祖先是哪一个节点。
树的读入格式:n-1行每行两个整数x、y,表示一条连接x和y的边,保证输入的图形成一棵树。
输入格式:
第一行两个整数为n和q,之后按题目描述读入一棵树。
再之后q行,每行两个整数x和y,表示一组询问。
输出格式:
q行,每行1个整数表示答案。
样例输入1:
10 5
2 1
2 3
2 4
5 4
3 6
7 6
8 1
1 9
1 10
9 8
3 1
7 4
6 2
10 7
样例输出1:
1
1
2
2
1
\(1\le n,q\le 10^5\)
设 \(fa_{x,i}\) 表示 \(x\) 的 \(2^i\) 级祖先,由二进制可知正确性(循环时i从大到小,详见代码),可以 \(O(n\log n)\)预处理,\(O(\log n)\)查询。
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
vector<int>g[N];
int fa[N][21],n,q,dep[N];
void dfs(int u,int deep,int fat) {
fa[u][0]=fat;
dep[u]=deep;
for(int i=0; i<g[u].size(); ++i) {
int v=g[u][i];
if(v==fat)continue;
dfs(v,deep+1,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=20;i>=0;--i)
if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=20;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",&n,&q);
for(int i=1,x,y;i<n;++i)
{
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1,1,1);
for(int i=1; i<=20; ++i) {
for(int j=1; j<=n; ++j) {
fa[j][i]=fa[fa[j][i-1]][i-1];
}
}
while(q--)
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}
倍增求LCA(最近公共祖先)的更多相关文章
- 求LCA最近公共祖先的在线倍增算法模板_C++
倍增求 LCA 是在线的,而且比 ST 好写多了,理解起来比 ST 和 Tarjan 都容易,于是就自行脑补吧,代码写得容易看懂 关键理解 f[i][j] 表示 i 号节点的第 2j 个父亲,也就是往 ...
- 求LCA最近公共祖先的在线ST算法_C++
ST算法是求最近公共祖先的一种 在线 算法,基于RMQ算法,本代码用双链树存树 预处理的时间复杂度是 O(nlog2n) 查询时间是 O(1) 的 另附上离线算法 Tarjan 的链接: http ...
- 求LCA最近公共祖先的离线Tarjan算法_C++
这个Tarjan算法是求LCA的算法,不是那个强连通图的 它是 离线 算法,时间复杂度是 O(m+n),m 是询问数,n 是节点数 它的优点是比在线算法好写很多 不过有些题目是强制在线的,此类离线算法 ...
- cogs 2450. 距离 树链剖分求LCA最近公共祖先 快速求树上两点距离 详细讲解 带注释!
2450. 距离 ★★ 输入文件:distance.in 输出文件:distance.out 简单对比时间限制:1 s 内存限制:256 MB [题目描述] 在一个村子里有N个房子,一 ...
- 倍增求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 ...
- lca最近公共祖先(模板)
洛谷上的lca模板题--传送门 学了求lca的tarjan算法(离线),在洛谷上做模板题,结果后三个点超时. 又把询问改成链式前向星,才ok. 这个博客,tarjan分析的很详细. 附代码-- #in ...
- 【倍增】洛谷P3379 倍增求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- D5 LCA 最近公共祖先
第一题: POJ 1330 Nearest Common Ancestors POJ 1330 这个题可不是以1为根节点,不看题就会一直wa呀: 加一个找根节点的措施: #include<alg ...
随机推荐
- 高斯消元几道入门题总结POJ1222&&POJ1681&&POJ1830&&POJ2065&&POJ3185
最近在搞高斯消元,反正这些题要么是我击败了它们,要么就是这些题把我给击败了.现在高斯消元专题部分还有很多题,先把几道很简单的入门题总结一下吧. 专题:http://acm.hust.edu.cn/vj ...
- 【转】stm32 IAP升级程序
一.什么是IAP,为什么要IAP IAP即为In Application Programming(在应用中编程),一般情况下,以STM32F10x系列芯片为主控制器的设备在出厂时就已经 ...
- GoJS简单示例
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- Gcd&Exgcd
欧几里得算法: \[gcd(a,b)=gcd(b,a\bmod b)\] 证明: 显然(大雾) 扩展欧几里得及证明: 为解决一个形如 \[ax+by=c\] 的方程. 根据裴蜀定理,当且仅当 \[gc ...
- 对于文章的字母、单词、短语,(无用词表)的检索Java代码实现
日期:2019.5.9 博客期:073 星期四 今天软件工程课上,又做了测试,老师说我们的速度太慢了,实际上我也觉得自己很慢.老师说了这是我们的上一届的大二上半学期学习中的速度,所以呢?意思就是说我们 ...
- 深入理解 C# 协变和逆变 (转载)
深入理解 C# 协变和逆变 msdn 解释如下: “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型. “逆变”则是指能够使用派生程度更小的类型. 解释的很正确,大致就是这样,不过不 ...
- 2020寒假 05 ——eclipse安装scala环境
在eclipse中安装Scala环境 1安装eclipse插件步骤,点击help,选择Eclipse Marketplace 2.输入Scala,点击go 3.选择搜索到的Scala IDE 4.7. ...
- Java If ... Else
章节 Java 基础 Java 简介 Java 环境搭建 Java 基本语法 Java 注释 Java 变量 Java 数据类型 Java 字符串 Java 类型转换 Java 运算符 Java 字符 ...
- F. Fairness 分硬币最大差值最小
F. Fairness time limit per test 2.0 s memory limit per test 64 MB input standard input output standa ...
- redis学习(三)
一.Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 二.Redis 命令 1 ...