当前位置:网站首页>最近公共祖先(LCA)在线做法
最近公共祖先(LCA)在线做法
2022-07-01 19:36:00 【Zqchang】
祖先
在一个有根树中,路过的点都被称为祖先,为了一般画我们把一个点本身也成为祖先,这样每个点都会有很多祖先,最近公共祖先就是,给我们两个点,离他们俩最近的一个公共祖先就是最近公共祖先,如图
如果两个点是重叠的,最近公共祖先就是它自己
求法
向上标记法(不常用)
从一个点开始,向根节点便利,遍历的过程当中,把他路过的所有的点标记一下 ,然后从另一个点做相同操作,当第一次走到被标记的的点的时候就是最近公共祖先,这个时间复杂度是O(n)的
倍增
先预处理一下每个点向上走 2 k 2^k 2k步的父亲是谁。
fa[i][j]表示从i开始,向上走 2 j 2^j 2j步所能走到的所有节点, 0 <= j <= logn(以2为底)
用递推的方式进行预处理
如图,也就是要求从i这个点开始,向上走 2 j 2^j 2j步,之后的点,接下来分成两种情况,第一种就是j=0,答案就是i的父节点,当j>0的时候,就分成两步,先跳到 2 j − 1 2^{j - 1} 2j−1,然后从这个点再往后跳 2 j − 1 2^{j - 1} 2j−1步,就跟图中一样
depth[]表示深度,规定根节点深度是1,然后根节点子节点的深度是2,再子节点深度是3,以此类推,就是到根节点的距离+1
这两个数组都可以用dfs 或者bfs来求
距离
求xy这两个点的公共祖先,分两步
1.先将两个点跳到同一层,其实就是让较深的那个点跳到跟较浅的那个点的同一层,这里就是把x跳到和y同一层
基于一个二进制拼凑的思想,比如已经预处理出来了2的k次方以内的数,想要凑出来t,就是看一下t的二进制表示,然后凑出来,就直接从小到大看,只要t大于2的当前位次方,就说明t是要包含这一个的,然后边减边比较
然后,应用到lca里面就是,x要跳到y,需要跳的就是depth[y] - depth[x]步,然后已经预处理出来了f[i][j]就从大到小枚举一下,凑出来这个数就好实际上不用凑出来这个数,只需要在枚举的时候,只要满足
这个条件就可以往上跳
2.让两个点同时往上跳(如果第一步进行完之后就是同一个点了的话,就可以直接结束,不用第二步了),一直到两个都是公共祖先的下一层为止,之所以不直接跳到公共祖先是为了方便判断
如果f[a][k] = f[b][k]的话,我们只能说f[a][k] 和f[b][k]是a和b的一个公共祖先,并不能说是最近公共祖先,但是如果f[a][k] != f[b][k]的话,就意味着f[a][k] = f[b][k]还没有走到公共祖先上,正因为这一点,才让跳到公共祖先的下一个点,就是如果相等的话,无法判断这个点是不是最近公共祖先,因为它还可能是最近公共祖先的上面的一个点,这无法判断
跳的时候也是按照二进制拼凑的思想,从大往小来枚举k,在枚举的过程当中,只要我们跳 2 K 2^K 2K步之后f[a][k] != f[b][k],就说明他们还没有跳到应有的位置,就是还没有跳到最近公共祖先上,就可以让他们一起往上跳一次,直到k枚举完为止,枚举完之后x和y就算是走到了公共祖先的下一层,这时候,他们的公共祖先应该是从x或者y往上跳一步
这两步时间复杂度都是logn,预处理时间复杂度是nlogn的,这种倍增求lca的方式也是最常用的一种方式
在实际过程中,还会设置哨兵
基于RMQ的做法
首先把整棵树dfs遍历一遍,遍历的过程中记录一下dfs序列,这里记录的时候是每次遍历到,无论是回溯还是首次遍历都要记录一下,以下图为例
dfs序列应该是
这里还是找x和y之间距离,那就是一个8一个5,随便一个8一个5都可以,然后就转变成了区间最小值问题,就可以用RMQ或线段树来做
例题
板子题不解释
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define fast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 40010;
vector<int> v[N];
int depth[N], fa[N][16];
queue<int> q;
int root, n, m;
void bfs()
{
memset(depth, 0x3f, sizeof depth);
depth[0] = 0; depth[root] = 1;
q.push(root);
while(q.size())
{
int t = q.front();
q.pop();
for(auto i : v[t])
{
if(depth[i] > depth[t] + 1)
{
depth[i] = depth[t] + 1;
q.push(i);
fa[i][0] = t;
for(int j=1; j<=15; j ++)
{
fa[i][j] = fa[fa[i][j - 1]][j - 1];
}
}
}
}
}
int lca(int a, int b)
{
if(depth[a] < depth[b]) swap(a, b);
for(int i=15; i>=0; i--)
if(depth[fa[a][i]] >= depth[b])
a = fa[a][i];
if(a == b) return a;
for(int i=15; i>=0; i--)
if(fa[a][i] != fa[b][i])
{
a = fa[a][i];
b = fa[b][i];
}
return fa[a][0];
}
signed main()
{
fast;
cin >> n;
int a, b;
for(int i=1; i<=n; i++)
{
cin >> a >> b;
if(b == -1) root = a;
else
{
v[a].push_back(b);
v[b].push_back(a);
}
}
bfs();
cin >> m;
while(m --)
{
cin >> a >> b;
int p = lca(a, b);
if(p == a) puts("1");
else if(p == b) puts("2");
else puts("0");
}
return 0;
}
边栏推荐
- 深度学习 神经网络基础
- GCC编译
- Entering Ruxin Town, digital intelligence transformation connects "future community"
- 牛客编程题--必刷101之字符串(高效刷题,举一反三)
- Use Zadig to build a continuous delivery platform from 0 to 1
- Slf4j打印异常的堆栈信息
- 【mysql 07】GPG key retrieval failed: “Couldn‘t open file /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql-2022“
- 【级联分类器训练参数】Training Haar Cascades
- What if the win11 shortcut key switching input method doesn't respond? Shortcut key switching input method does not respond
- 薛定谔的日语学习小程序源码
猜你喜欢
在技术升级中迎合消费者需求,安吉尔净水器“价值战”的竞争之道
杰理之、产线装配环节【篇】
强大的万年历微信小程序源码-支持多做流量主模式
新牛牛盲盒微信小程序源码_支持流量变现,带完整素材图片
After adding cocoapods successfully, the header file cannot be imported or an error is reported in not found file
以飞地园区为样本,看雨花与韶山如何奏响长株潭一体化发展高歌
Penetration tools - trustedsec's penetration testing framework (PTF)
Use Zadig to build a continuous delivery platform from 0 to 1
300 linear algebra Lecture 4 linear equations
Past and present life of product modular design
随机推荐
Richview RichEdit srichviewedit PageSize page setup and synchronization
On the next generation entrance of the metauniverse -- the implementation of brain computer interface
朋友圈社区程序源码分享
EMC-电路保护器件-防浪涌及冲击电流用
网上开户是安全的吗?新手可以开炒股账户吗。
人脸识别系统 —— OpenCV人脸检测
NSI脚本的测试
What if win11 can't pause the update? Win11 pause update is gray. How to solve it?
Learn white box test case design from simple to deep
喜马拉雅自研网关架构演进过程
Keras machine translation practice
Comprehensive evaluation and detailed inventory of high-quality note taking software (I) note, obsedian, remnote, flowus
升级版手机检测微信工具小程序源码-支持多种流量主模式
目標檢測——Yolo系列
leetcode刷题:二叉树02(二叉树的中序遍历)
宅男壁纸大全微信小程序源码-带动态壁纸支持多种流量主
What else do you not know about new set()
柒微自动发卡系统源码
走进如心小镇,数智化变革连接“未来社区”
芭比Q了!新上架的游戏APP,咋分析?