树上倍增求LCA
大概思想就是,节点$i$的第$2^{j}$个父节点是他第$2^{j-1}$个父亲的第$2^{j-1}$个父亲
然后可以$O(nlogn)$时间内解决……
没了?
//fa[i][j]表示i的第2^j个父节点
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct edge{
int v,next;
}a[];
int n,q,u,v,rt,tot=,head[],fa[][],dep[];
bool vis[];
void add(int u,int v){
a[++tot].v=v;
a[tot].next=head[u];
head[u]=tot;
}
void cal_dep(int u){
vis[u]=true;
for(int tmp=head[u];tmp!=-;tmp=a[tmp].next){
int v=a[tmp].v;
if(!vis[v]){
dep[v]=dep[u]+;
cal_dep(v);
}
}
}
void cal(){
for(int j=;j<=;j++){
for(int i=;i<=n;i++){
fa[i][j]=fa[fa[i][j-]][j-];
}
}
}
int lca(int x,int y){
if(dep[x]<dep[y]){
swap(x,y);
}
int s=dep[x]-dep[y];
for(int i=;i<;i++){
if((<<i)&s)x=fa[x][i];
}
if(x==y)return x;
for(int i=;i>=;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];
y=fa[y][i];
}
}
return fa[x][];
}
int main(){
memset(head,-,sizeof(head));
memset(fa,,sizeof(fa));
memset(dep,,sizeof(dep));
memset(vis,,sizeof(vis));
scanf("%d%d",&n,&q);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
fa[v][]=u;
//if(!fa[u][0])rt=u;
}
dep[]=;
cal_dep();
cal();
for(int i=;i<=q;i++){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return ;
}
/*
16 4
1 2
1 3
2 4
2 5
2 6
3 7
4 8
4 9
5 10
7 11
7 12
10 13
10 14
10 15
12 16
4 7
9 16
11 16
15 8
------
1
1
7
2
*/
树上倍增求LCA的更多相关文章
- [学习笔记] 树上倍增求LCA
倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- 树上倍增求LCA及例题
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...
- Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)
题面 传送门 题目大意: 给定一个无向连通带权图G,对于每条边(u,v,w)" role="presentation" style="position: rel ...
- 树上倍增求LCA详解
LCA(least common ancestors)最近公共祖先 指的就是对于一棵有根树,若结点z既是x的祖先,也是y的祖先(不要告诉我你不知道什么是祖先),那么z就是结点x和y的最近公共祖先. 定 ...
- [luogu3379]最近公共祖先(树上倍增求LCA)
题意:求最近公共祖先. 解题关键:三种方法,1.st表 2.倍增法 3.tarjan 此次使用倍增模板(最好采用第一种,第二种纯粹是习惯) #include<cstdio> #includ ...
- CF 519E(树上倍增求lca)
传送门:A and B and Lecture Rooms 题意:给定一棵树,每次询问到达点u,v距离相等的点有多少个. 分析:按情况考虑: 1.abs(deep[u]-deep[v])%2==1时, ...
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
随机推荐
- RocketMQ学习笔记(11)----RocketMQ的PushConsumer和PullConsumer
1. PushConsumer 推,Broker主动向Consumer推消息,它Consumer的一种,应用通常向对象注册一个Listener接口,一旦接收到消息,Consumer对象立刻回调Lins ...
- NGUI 按钮点击事件的两种绑定形式
面板属性栏绑定 写一个脚本,定义一个Public的方法 Notify中选择物体时,选中自己 然后就可以选择通知到写的那个脚本的里边的public方法 代码绑定 创建一个代码文件,挂载到按钮对象上 代码 ...
- ZBrush软件特性之Layers
ZBrush®中的Layers层调控板可以在单个文档工作中添加多个层,实际上是把新建的层作为一个分离的文档,层之间可以相互影响. 使用层工作 Layers调控板为每个层都有预置存放的空间,刚启动ZBr ...
- Python中int,bool,str,格式化,少量is,已经for循环练习
1.整数 十进制转化为二进制 xxx.bit_length(). #求十进制数转化成二进制时所占用的位数 2.布尔值 bool # 布尔值 - - 用于条件使用 True 真 Fa ...
- es6——Proxy和Reflect
Proxy代理,Reflect反射 Proxy对属性的读取 { //供应商,原始对象 let obj={ time:'2017-1-1', name:'net', _r:123 } //代理商,新生成 ...
- Python基础数据类型list,tuple
列表是有序的可变的元素集合.列表中的每个元素可以使任何数据类型,包括列表本身. 列表生成 Python3中的列表通过定义,for循环,列表推导式等几种方式生成 定义 直接通过中括号`[]`定义一个列表 ...
- python之静态属性、类方法、静态方法
静态属性.类方法.静态方法 1. 静态属性:在函数前加@property,将函数逻辑”封装“成数据属性,外部直接调用函数名,如同调用属性一样.这个函数是可以调用类和实例的属性的, 静态属性的作用 ...
- BeanUtils(前端赋值给后台,忽略空属性)
package com.drn.core.util; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; im ...
- ubuntu18.04crontab定时任务不执行
环境介绍: 本人使用python写了一个自动化提交巡检的脚本放在服务器上,使用crontab去执行脚本的时候动作并没有执行,查看crontab日志时也不存在这个日志文件.如何如排查呢? 解决方案: 步 ...
- mysql局域网服务搭建
首先配置电脑Mysql环境变量 新建 Mysql服务配置 CMD >命令 : mysql -u root -p 4. 创建用户 Mysql 用户权限分配 5 重启服务 如果还不能访问就一定是你的 ...