[luogu3379]最近公共祖先(树上倍增求LCA)
题意:求最近公共祖先。
解题关键:三种方法,1、st表 2、倍增法 3、tarjan
此次使用倍增模板(最好采用第一种,第二种纯粹是习惯)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,root,cnt,u,v,head[],dep[],fa[][];
struct edge{
int nxt;
int to;
}e[];
void add_edge(int u,int v){//单向
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int u){
for(int i=;(<<i)<=dep[u];i++){
fa[u][i]=fa[fa[u][i-]][i-];
}
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[u][]) continue;
fa[v][]=u;
dep[v]=dep[u]+;
dfs(v);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v];
for(int i=;(<<i)<=d;i++) if(d&(<<i)) u=fa[u][i];//转化到两节点深度相同,类似于快速幂的思想
if(u==v) return u;
for(int i=;i>=;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
}
return fa[u][];
}
int main(){
memset(head,-,sizeof head);
scanf("%d%d%d",&n,&m,&root);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(root);
while(m--){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return ;
}
2、熟悉的树dp方式
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
int n,m,root,cnt,u,v,head[],dep[],par[][];
struct edge{
int nxt;
int to;
}e[];
void add_edge(int u,int v){//单向
e[cnt].to=v;
e[cnt].nxt=head[u];
head[u]=cnt++;
}
void dfs(int u,int fa){
for(int i=;(<<i)<=dep[u];i++){
par[u][i]=par[par[u][i-]][i-];
}
for(int i=head[u];~i;i=e[i].nxt){
int v=e[i].to;
if(v==fa) continue;
par[v][]=u;
dep[v]=dep[u]+;
dfs(v,u);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v];
for(int i=;(<<i)<=d;i++) if(d&(<<i)) u=par[u][i];//转化到两节点深度相同,类似于快速幂的思想
if(u==v) return u;
for(int i=;i>=;i--){
if(par[u][i]!=par[v][i]){
u=par[u][i];
v=par[v][i];
}
}
return par[u][];
}
int main(){
memset(head,-,sizeof head);
scanf("%d%d%d",&n,&m,&root);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
dfs(root,-);
while(m--){
scanf("%d%d",&u,&v);
printf("%d\n",lca(u,v));
}
return ;
}
[luogu3379]最近公共祖先(树上倍增求LCA)的更多相关文章
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- [学习笔记] 树上倍增求LCA
倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...
- 树上倍增求LCA及例题
先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...
- 树上倍增求LCA详解
LCA(least common ancestors)最近公共祖先 指的就是对于一棵有根树,若结点z既是x的祖先,也是y的祖先(不要告诉我你不知道什么是祖先),那么z就是结点x和y的最近公共祖先. 定 ...
- Codeforces 609E (Kruskal求最小生成树+树上倍增求LCA)
题面 传送门 题目大意: 给定一个无向连通带权图G,对于每条边(u,v,w)" role="presentation" style="position: rel ...
- CF 519E(树上倍增求lca)
传送门:A and B and Lecture Rooms 题意:给定一棵树,每次询问到达点u,v距离相等的点有多少个. 分析:按情况考虑: 1.abs(deep[u]-deep[v])%2==1时, ...
- 树上倍增求LCA
大概思想就是,节点$i$的第$2^{j}$个父节点是他第$2^{j-1}$个父亲的第$2^{j-1}$个父亲 然后可以$O(nlogn)$时间内解决…… 没了? //fa[i][j]表示i的第2^j个 ...
- 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))
倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...
随机推荐
- 如何理解python中的if __name__=='main'的作用
一. 一个浅显易懂的比喻 我们在学习python编程时,不可避免的会遇到if __name__=='main'这样的语句,它到底有什么作用呢? <如何简单地理解Python中的if __name ...
- 解决:SyntaxError: Non-ASCII character in file
今天尝试用monkeyrunner脚本在夜神模拟器上安装并截图QQ,但是遇到了一些问题: from com.android.monkeyrunner import MonkeyRunner, Monk ...
- 团队小组NABCD(通用作业和个人作业)特点
NABCD框架(通用作业和个人作业): N(need,需求): 你的创意解决了用户的什么需求? 使用户能够很好的区分作业情况,将班里所有同学的作业和自己私人的作业分开,通用作业指在一个班一同上课的公共 ...
- hzau 1203 One Stroke
1203: One Stroke Time Limit: 2 Sec Memory Limit: 1280 MBSubmit: 264 Solved: 56[Submit][Status][Web ...
- Linux中几个实用快捷键
返回上层目录: cd .. 命令提示符: user@ubuntu: @之前的部分为当前用户ID名称: @之后冒号之前是主机名称 sudo :(Superusers Do) 以超级用户执行 在相对路径 ...
- Java垃圾回收机制——finallize()
其实了解JAVA的人,都知道JAVA的GC机制是其的一大优点,它令程序员不需要主动去考虑内存溢出和垃圾回收的问题,不像c++具有显式的析构函数对整个对象进行内存清理以及需要调用delete才可以进行显 ...
- Spark入门实战系列
转自:http://www.cnblogs.com/shishanyuan/p/4699644.html 这一两年Spark技术很火,自己也凑热闹,反复的试验.研究,有痛苦万分也有欣喜若狂,抽空把这些 ...
- python 调试命令
部分整理自:http://flysnowxf.iteye.com/blog/1327677 启动调试: python -m pdb xxx.py 常用命令说明: l #查看运行到哪行代码 n #单步运 ...
- 【java规则引擎】之Drools引擎中模拟ReteooStatefulSession内部设计结构
该片文章只是抽取drools中java代码实现的一些代码结构,帮助我们理解drools是如何实现rete算法的. 该部分只是抽取ReteooStatefulSession工作过程中的代码架构 利用了多 ...
- 循环比赛日程表(match)(分治)
[问题描述] 设有N个选手进行循环比赛,其中N=2M,要求每名选手要与其他N-1名选手都赛一次,每名选手每天比赛一次,循环赛共进行N-1天,要求每天没有选手轮空. 输入:M 输 ...