LCA算法——倍增
概况
LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。
#include<bits/stdc++.h>
#include<queue>
using namespace std;
const int N=5e5+5;
int n,m,s;
int root;
int idx=1;
int ver[2*N],nex[2*N],head[2*N],dis[2*N],f[2*N][25];
queue<int>q;
int t; void add(int x,int y) {//邻接表建图
ver[++idx]=y;
nex[idx]=head[x];
head[x]=idx;
return ;
} void bfs() {//bfs会比dfs更加保险
q.push(root);
dis[root]=1;//根节点的深度为1
while(!q.empty()) {
int x=q.front();
q.pop();
for(int i=head[x]; i; i=nex[i]) {//向下一层搜索
int y=ver[i];
if(dis[y]) continue;//防止死循环
dis[y]=dis[x]+1;//深度更新
f[y][0]=x;//2^0=1,即为y的父结点
for(int j=1; j<=t; j++) {
f[y][j]=f[f[y][j-1]][j-1];//更新2^i个祖先
}
q.push(y);
}
}
return ;
} int lca(int x,int y) {
if(dis[x]<dis[y]){//严格规范dis[x]>dis[y]
swap(x,y);
}
for(int i=t; i>=0; i--) {
if(dis[f[x][i]]>=dis[y]) x=f[x][i];//使x和y的深度相同
}
if(x==y) return x;//已经相同,则直接返回x
for(int i=t; i>=0; i--) {
if(f[x][i]!=f[y][i]) {//如果第2^i个祖先不相同,说明还没有到最小公共祖先
x=f[x][i];
y=f[y][i];//更新x,y
}
}
return f[x][0];//返回x的父节点——即最小公共祖先
} int main() {
cin>>n;
t=(log(n)/log(2))+1;
for(int i=1; i<=n; i++) {
int a,b;
cin>>a>>b;
if(b==-1) root=a;
add(a,b);
add(b,a);
}
bfs();
cin>>m;
for(int i=1; i<=m; i++) {
int x,y;
cin>>x>>y;
if(lca(x,y)==x) cout<<1<<endl;
if(lca(x,y)==y) cout<<2<<endl;
if(lca(x,y)!=x&&lca(x,y)!=y) cout<<0<<endl;
}
// for(int i=1;i<=5;i++)cout<<i<<":"<<dis[i]<<endl;
return 0;
}
LCA算法——倍增的更多相关文章
- LCA算法倍增算法(洛谷3379模板题)
倍增(爬树)算法,刚刚学习的算法.对每一个点的父节点,就记录他的2k的父亲. 题目为http://www.luogu.org/problem/show?pid=3379 第一步先记录每一个节点的深度用 ...
- LCA的倍增算法
LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...
- 关于LCA的倍增解法的笔记
emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w 首先 何为LCA? LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主 ...
- [模板]LCA的倍增求法解析
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 【图论】tarjan的离线LCA算法
百度百科 Definition&Solution 对于求树上\(u\)和\(v\)两点的LCA,使用在线倍增可以做到\(O(nlogn)\)的复杂度.在NOIP这种毒瘤卡常比赛中,为了代码的效 ...
- LCA + 二分(倍增)
两个最近的点u和v的最近的公共的祖先称为最近公共祖先(LCA).普通的LCA算法,每算一次LCA的时间复杂度为线性o(n); 这里讲LCA + 二分的方法.首先对于任意的节点v,利用其父节点的信息,可 ...
- LCA算法
LCA算法: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共 ...
- LCA算法解析-Tarjan&倍增&RMQ
原文链接http://www.cnblogs.com/zhouzhendong/p/7256007.html UPD(2018-5-13) : 细节修改以及使用了Latex代码,公式更加美观.改的过程 ...
- LCA 算法(二)倍增
介绍一种解决最近公共祖先的在线算法,倍增,它是建立在任意整数的二进制拆分之上. 代码: //LCA:Doubly #include<cstdio> #define swap(a, ...
随机推荐
- java实现发送短信验证码
java实现短信验证码发送 由于我们使用第三方平台进行验证码的发送,所以首先,我们要在一个平台进行注册. 在这里我选择是秒嘀科技,因为新人注册会赠送十元,足够测试使用了. 注册完成后,我们需要获取自己 ...
- 一键配置网卡IP(win10)脚本
前两天有个小伙伴问我,如何快速配置IP,在公司在家里在宿舍,快速配置IP,然后我特别为这个小伙伴写了一个脚本. @echo off mode con: cols=60 lines=25 title 网 ...
- ABP vNext 自动注入,暗藏天坑如斯
导言 我们在使用ABP vNext框架时,都知道该框架为我们实现了自动依赖注入(实现自动注入需要在项目里面创建Module类,并且将Module类上的DependsOn到相应的启动Module类或调用 ...
- 十六:SQL注入之查询方式及报错盲注
在很多注入时,有很多注入会出现无回显的情况,其中不回显的原因可能是SQL查询语句有问题,这时候我们需要用到相关的报错或者盲注进行后续操作,同时作为手工注入的时候,需要提前了解SQL语句能更好的选择对应 ...
- VBA实现相同行合并
帮人捣鼓了个VBA代码用来实现多行合并,具体需求为:列2/列3/列4 相同的情况下,则对应的行合并为一行,且列1用空格隔开,列5则相加: (对大多数办公室职员,VBA还算是提高效率的一个利器吧) 最终 ...
- MySQL全面瓦解16:存储过程相关
概述 大多数SQL语句都是针对一个或多个表的单条语句.但并非所有业务都这么简单,经常会有复杂的操作需要多条语句才能完成. 比如用户购买一个商品,要删减库存表,要生成订单数据,要保存支付信息等等,他是一 ...
- 改进你的c#代码的5个技巧(四)
像每一篇文章一样,我会重复几行.我在我的Core i3 CPU.4GB主内存和Windows 7平台上测试了以下代码.如果你在不同的硬件配置或使用不同的平台,那么你的输出可能会随着我的输出屏幕而变化, ...
- Java调用Linux命令执行
调用方式 Java调用linux命令执行的方式有两种,一种是直接调用linux命令,一种是将linux命令写到.sh脚本中,然后调用脚本执行. 详细说明 直接调用:使用java中lang包下面的Run ...
- CTFhub刷题记录
一 [WesternCTF2018]shrine 没什么好说的,SSTI模版注入类问题,过滤了()但是我们不慌.开始注入,{{29*3}}测试通过. 发现是jinjia2的模版注入.关键点在于没有() ...
- SDNU_ACM_ICPC_2021_Winter_Practice_1st [个人赛] 2021.1.19 星期二
SDNU_ACM_ICPC_2021_Winter_Practice_1st [个人赛] K - Color the ball 题意: 有n个气球,每次都给定两个整数a,b,给a到b内所有的气球涂一个 ...