首页 > 其他分享 >倍增求lca

倍增求lca

时间:2025-01-16 14:45:53浏览次数:1  
标签:int son fa depth lca 倍增 节点

非常重要的东西
我甚至模拟赛都不打了来打笔记
很简单啊,朴素lca是这样,两个节点,先令深度相等,然后一个一个往上跳直到跳到相同的位置则那个点为两点的lca
但是令深度相等与往上跳的过程都要一个一个慢慢跳所以时间复杂度拉满了
那么我们能以什么方式优化呢
我们可以发现,每个数都可以用几个二的几次方的和的方式来表示
把一个一个往上跳的过程抽象成下图一样在数组中跳至指定位置
比如从1到7
我们可以直接一个一个跳过去
也可以预处理一个数组--x[i][j]:第i个数向右跳2^j到达的数
举个例子a[1]往右跳2^1是2[3]呈现在数组中就是x[1][1]==3
于是我们就可以
从一到五
从五到七
由此很轻易可以知道怎么树上倍增
定义fa[i][j]:第i个节点向上跳2^j到达的父节点
于是我们就可以用这个思想来优化O(n)的令深度相等与往上跳的过程成O(logn)
damn码:

#include<bits/stdc++.h>
using namespace std;
vector<int> e[500005];//存图
int fa[500005][20],depth[500005];
//fa[i][j]表示i上方第2的j次方的祖先,比如fa[i][0]就是i的父亲,depth存储深度,根节点深度为1
void init(int son,int father){//初始化,两个变量英文即为含义
	depth[son]=depth[father]+1;//子节点是父亲节点的深度加1
	fa[son][0]=father;//将son的第一个祖先设为父亲
	for(int i=1;i<20;i++) fa[son][i]=fa[fa[son][i-1]][i-1];
    /*这句话翻译过来是:son跳2的i次方到达的点是它跳2的i-1次方步后再跳2的i-1次方能到的点
      还是举本文章第一张图的例子,
      那么5的父亲节点为3,即5跳一步能到3;5跳两步(即fa[5][1])到1,3跳一步(即fa[3][0])到1
      也就是将跳好多步转化为两个部分,从“一跳到位”变成“跳一会儿,休息一会儿,再跳一会儿”
      大家也可以尝试其它例子帮助理解
    */
	for(int i=0;i<e[son].size();i++){
		if(e[son][i]!=father) init(e[son][i],son);
       //遍历son的连边,不是它的爸爸就是它的儿子,那就进去登记父子关系。
	}
}
int lca(int x,int y){
	if(depth[x]<depth[y]) swap(x,y);//默认x比y深度大,没有的话换一下就好了,减少代码难度
	for(int i=19;i>=0;i--){
		if(depth[fa[x][i]]>=depth[y]){ //只要比y深就继续跳直到一样
			x=fa[x][i];
		}
		
	} 
	if(x==y) return x;//如果已经相等了直接返回就行
	for(int i=19;i>=0;i--){//没有就一起跳,直到找到为止
		if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
	}
	return fa[x][0];
}
int main(){
	int n,m,s;
	scanf("%d%d%d", &n, &m, &s);//用scanf或快读都行,cin会超时
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d", &x, &y);
		e[x].push_back(y);//无向图
		e[y].push_back(x);
	}
	init(s,0);//0是一个虚节点,因为没有节点是0,现在我们添加一个深度为0的0节点,便于处理根节点
	while(m--){
		int a,b;
		scanf("%d%d", &a, &b);
		cout<<lca(a,b)<<endl;
	}
	return 0;
} 

标签:int,son,fa,depth,lca,倍增,节点
From: https://www.cnblogs.com/2xinxin/p/18674453

相关文章

  • 倍增算法【模板】
    原题链接https://www.luogu.com.cn/problem/P3865题解链接https://blog.csdn.net/WJTF2/article/details/136239183?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522423e6dee0d2c53e9645ecba193312fb3%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257......
  • 解决htmlcanvas遇到图片较多的复杂首页,保存截图特别慢的问题
    先说问题:在首页新增个保存部分dom截图的功能,但首页加载接口较多,图片跨域加载比较慢,而htmlcanvas保存截图前会将整个页面渲染一遍,这就导致有些图片没加载完成,dom渲染不然,canvas保存就会延迟四五秒之久 解决方法:增加这个参数ignoreElements:function(element){......
  • k8s volcano + deepspeed多机训练 + RDMA ROCE+ 用户权限安全方案
    前提:nvidia、cuda、nvidia-fabricmanager等相关的组件已经在宿主机正确安装,如果没有安装可以参考我之前发的文章GPUA800A100系列NVIDIA环境和PyTorch2.0基础环境配置【建议收藏】_a800多卡运行环境配置-CSDN博客文章浏览阅读1.1k次,点赞8次,收藏16次。Ant系列GPU支持NvLink&N......
  • (即插即用模块-Attention部分) 四十一、(2023) MLCA 混合局部通道注意力
    文章目录1、MixedLocalChannelAttention2、代码实现paper:MixedlocalchannelattentionforobjectdetectionCode:https://github.com/wandahangFY/MLCA1、MixedLocalChannelAttention现有通道注意力机制的局限性:大多数通道注意力机制只关注通道特征信......
  • 关于此题[ABC367E] Permute K times倍增思想的一些总结
    传送门第一次接触到倍增思想是用来求lca时,为了避免一层一层往上爬浪费时间复杂度。再后来就是区间DP中一小类问题或者是部分图上问题可以用倍增来优化。那么这道题其实可以看作图上问题来使用倍增优化。看到这道题的数据范围,K达到了\(10^{18}\)量级,这让我们不得不思考log级别往......
  • 二分 + 倍增 做题笔记
    一些关于二分和倍增的题,大体按照题目难度排序。1.CF1951HThanosSnap简要题意给定一个长为\(2^n\)的序列\(a_0,a_1,\cdots,a_{2^n-1}\),对所有\(t\in[1,n]\)求解如下问题:A和B两人在序列\(a\)上博弈,一共进行\(t\)轮操作。每轮操作的流程如下:A可以选......
  • 智能升级:构建由Open AI驱动的实时交易系统,倍增收益潜力(附源代码)
    作者:老余捞鱼原创不易,转载请标明出处及原作者。写在前面的话:在金融科技的浪潮中,实时数据处理和智能决策的重要性日益凸显。在本文中,我将分享如何利用Kafka和LlamaIndex构建一套基于GPT-4o的高效人工智能实时交易系统。从下载和分析欧元/美元对的日线数据,到设置Kafka数......
  • E92 换根DP+倍增 P5666 [CSP-S2019] 树的重心
    视频链接:E92换根DP+倍增P5666[CSP-S2019]树的重心_哔哩哔哩_bilibili   P5666[CSP-S2019]树的重心-洛谷|计算机科学教育新生态(luogu.com.cn)//换根DP+倍增O(nlogn)#include<iostream>#include<cstring>#include<algorithm>#include<vector>us......
  • 破解多区域协作难题,打造无缝连接新生态,让企业效率倍增!
    跨国公司在全球范围内拥有多个分支机构、生产基地和供应链,为了实现高效的运营和多区域协作,跨国公司需要建立稳定、安全的网络连接,确保不同地区之间的数据传输顺畅。例如,苹果、微软、可口可乐等全球知名企业均在全球范围内进行商品和服务的国际贸易、资本投资以及资产配置和整合。......
  • 最近公共祖先(LCA)笔记
    最近公共祖先(LCA)笔记【模板】最近公共祖先(LCA)题目入口题目描述如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。输入格式第一行包含三个正整数\(N,M,S\),分别表示树的结点个数、询问的个数和树根结点的序号。接下来\(N-1\)行每行包含两个正整数\(x,y\),表示......