概况

LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。

实现过程
预处理:通过dfs遍历,记录每个节点到根节点的距离dist[u],深度d[u]
init()求出树上每个节点u的2^i祖先p[u][i]
求最近公共祖先,根据两个节点的的深度,如不同,向上调整深度大的节点,使得两个节点在同一层上,如果正好是祖先结束,否则,将两个节点同时上移,查询最近公共祖先。
代码:
#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算法——倍增的更多相关文章

  1. LCA算法倍增算法(洛谷3379模板题)

    倍增(爬树)算法,刚刚学习的算法.对每一个点的父节点,就记录他的2k的父亲. 题目为http://www.luogu.org/problem/show?pid=3379 第一步先记录每一个节点的深度用 ...

  2. LCA的倍增算法

    LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...

  3. 关于LCA的倍增解法的笔记

    emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w 首先 何为LCA? LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主 ...

  4. [模板]LCA的倍增求法解析

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  5. 【图论】tarjan的离线LCA算法

    百度百科 Definition&Solution 对于求树上\(u\)和\(v\)两点的LCA,使用在线倍增可以做到\(O(nlogn)\)的复杂度.在NOIP这种毒瘤卡常比赛中,为了代码的效 ...

  6. LCA + 二分(倍增)

    两个最近的点u和v的最近的公共的祖先称为最近公共祖先(LCA).普通的LCA算法,每算一次LCA的时间复杂度为线性o(n); 这里讲LCA + 二分的方法.首先对于任意的节点v,利用其父节点的信息,可 ...

  7. LCA算法

    LCA算法: LCA(Least Common Ancestor),顾名思义,是指在一棵树中,距离两个点最近的两者的公共节点.也就是说,在两个点通往根的道路上,肯定会有公共的节点,我们就是要求找到公共 ...

  8. LCA算法解析-Tarjan&倍增&RMQ

    原文链接http://www.cnblogs.com/zhouzhendong/p/7256007.html UPD(2018-5-13) : 细节修改以及使用了Latex代码,公式更加美观.改的过程 ...

  9. LCA 算法(二)倍增

     介绍一种解决最近公共祖先的在线算法,倍增,它是建立在任意整数的二进制拆分之上.   代码:   //LCA:Doubly #include<cstdio> #define swap(a, ...

随机推荐

  1. 项目中处理数据常用Excel公式

    ="'"&A1&"'," 需求:是大佬给了excel,里面是700多个单号,要我从生产的数据库中查询出每个单号对应的类型,这时需要查数据库,我决 ...

  2. servlet+jsp完成简单登录

    将用户在注册界面中的数据填充到数据库相对应的表格中.当用户再次登录时,从数据库中拿到相应的数据查询并与页面的数据做对比,判断是否登陆成功. 需要在HTML文件中将form表单上的action属性值设置 ...

  3. kubernets之计算资源

    一  为pod分配cpu,内存以及其他的资源 1.1  创建一个pod,同时为这个pod分配内存以及cpu的资源请求量 apiVersion: v1 kind: Pod metadata: name: ...

  4. UVA - 185 Roman Numerals

    题目链接: https://vjudge.net/problem/UVA-185 思路: 剪枝.回溯 注意回溯的时候,是从当前点的下一个开始,而不是从已经遍历的个数点开始!!不然回溯有问题! 思路参考 ...

  5. 使用 gRPCurl 调试.NET 5的gPRC服务

    介绍 你用过 Curl 吗?这个工具允许你通过 http 来发送数据,现在有一个适用于gGRPC的工具,gRPCurl,在本文中,我将介绍如何下载安装这个工具,然后通过这个工具调试我们.NET 5上面 ...

  6. 记一次centos7重启后docker无法启动的问题

    问题描述 在重新了centos7系统后,docker突然就启动不了了,查看报错信息 [root@localhost ~]# systemctl status docker.service ● dock ...

  7. ctfhub技能树—RCE—命令注入

    打开靶机 查看页面信息 输入127.0.0.1进行测试 构造payload 127.0.0.1&ls 查看文件内容信息 127.0.0.1 & cat 179852221619745. ...

  8. Git安装/VScode+Git+Github

    Git安装/VScode+Git+Github 1. 相关简介 git 版本控制工具,支持该工具的网站有Github.BitBucket.Gitorious.国内的OS China仓库.Csdn仓库等 ...

  9. docker 运行时常见错误

    docker 运行时常见错误 (1) Cannot connect to the Docker daemon at unix:///var/run/docker.sock. [root@localho ...

  10. 2020 CSP&NOIP 游记

    CSP初赛 CSP初赛 Day -1 早上打了模拟赛,T2寒假正好做过,然而还是还是被踩Orz,郑外NB!.中午出校吃了大盘鸡和拉面,还带回来了三瓶可乐. 初赛知识点看了两页不(看)想(不)看(懂)了 ...