首页 > 其他分享 >最近公共祖先

最近公共祖先

时间:2023-12-02 17:44:25浏览次数:27  
标签:dep cnt 祖先 int add 最近 公共 500001 倍增

目录

倍增法求 LCA

倍增法

倍增法(英语:binary lifting),顾名思义就是翻倍。它能够使线性的处理转化为对数级的处理,大大地优化时间复杂度。

这个方法在很多算法中均有应用,其中最常用的是 RMQ 问题和求 LCA(最近公共祖先)。

实现

'f[x][i]' 表示 x 向上跳 \(2^i\) 步到达的结点编号。

$\huge{点我查看代码}$
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;

int f[500001][20];
int dep[500001];
int maxL;
const int N = 500001;

struct edge
{
    int to, nxt; // w是边长
}e[N*2];
int cnt, head[N];
void add(int x, int y)
{
    e[++cnt] = (edge){y, head[x]};
    head[x] = cnt;
}

void dfs(int x, int fa)
{
	dep[x] = dep[fa]+1;
	f[x][0] = fa;
	for(int i = 1;(1<<i) <= dep[x];i++)
	{
		f[x][i] = f[f[x][i-1]][i-1];
		maxL = max(i, maxL);
	}
	for(int i = head[x];i;i = e[i].nxt)
    {
        int y = e[i].to;
        if(y == fa) continue;
        dfs(y,x);
    }
}

int lca(int x, int y)
{
	if(dep[x] < dep[y]) swap(x,y);
	for(int i = maxL;i >= 0;i--)
		if(dep[x] - dep[y] >= (1<<i))
			x = f[x][i];
	if(x == y) return x;
	// 深度更大的点向上走,直到两点深度相同
	
	for(int i = maxL;i >= 0;i--)
		if(f[x][i] != f[y][i])
			 x = f[x][i], y = f[y][i];
	// 两点同时向上走,走到重合时停止
	
	return f[x][0];
	// 返回f[x][0];
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int n, m, s;
	cin >> n >> m >> s;
	for(int i = 1;i < n;i++)
	{
		int x, y;
		cin >> x >> y;
		add(x, y);
		add(y, x);
	}
	dfs(s,s);
	for(int i = 1;i <= m;i++)
	{
		int a, b;
		cin >> a >> b;
		cout << lca(a, b) << "\n";
	}
	return 0;
}

标签:dep,cnt,祖先,int,add,最近,公共,500001,倍增
From: https://www.cnblogs.com/ghivan911/p/17871920.html

相关文章

  • K最近邻算法
    汉堡店销售量预测某汉堡店每天都会做新鲜的汉堡,每天卖出的汉堡个数与天气等因素有关。请根据如下几个特征,用KNN算法预测当天售卖汉堡的个数。(1)天气指数1~5:1表示天气很差,5表示天气很好。(2)是否是周末:周末为1,否则为0。(3)是否有打折活动:1表示有打折,0表示没有打折。售出汉堡的历史数据表......
  • 最近碰见的电路故障问题
    1.接触器线圈工作电压要求。看下图说话。 故障:按启动按钮,接触器不吸合。原因:接触器线圈回路,因为启动按钮绿灯串联分压,导致接触器线圈电压测量时190V左右,达不到线圈吸合触点电压要求。改进后:  ......
  • 多种数据库获取最近一天记录的SQL整理
    多种数据库获取最近一天记录的SQL整理背景纯粹当笔记.数据库种类太多,记不住,每次都需要现查,效率实在是太低了将获取最近一天记录的SQL整理好方便后续直接his用简单总结Oracle+DM+神通的语法一样Kingbase+PG+Highgo的语法一样MySQL用的是SUB其他人都是......
  • [数据管理] 政务/公共大数据 # 中国地方公共数据开放利用报告(省域)-2023
    0序言2023年11月1日,复旦大学数字与移动治理实验室联合国家信息中心-数字中国研究院在“全球智慧城市大会·长沙”发布了“2023中国开放数林指数”和《中国地方公共数据开放利用报告——省域》。作为也曾经在政务大数据领域一线数据项目耕耘了整整2年的数据人,对这个领域仍......
  • P3379 【模板】最近公共祖先(LCA)
    原题链接非常详细的题解见洛谷,个人见解见代码#include<bits/stdc++.h>usingnamespacestd;#defineN500005vector<int>G[N];//链树,以链上的元素为根节点的树voidadd(intx,inty){G[x].push_back(y);G[y].push_back(x);}intfa[N][21]={0};intdepth[N]......
  • 最近公共祖先
    #include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;vector<ll>G[500000+10];lln,m,root;llf[500000+10][20],dep[500000+10],lg[500000+10];voiddfs(llu,llfa){ f[u][0]=fa; dep[u]=dep[fa]+1; for(lli=1;dep[u]-(1<<i)>......
  • 最近公共祖先(LCA)
    最近公共祖先(LCA)概念在有根树中,两个点,会有共同的祖先,离他们两最近的公共祖先,即为LCA求法向上表记法O(n)从一个点开始,向上遍历,把走过的点标记一下再从另外一个点开始,向上遍历,如果走到的点已经被标记,即为LCA最坏的情况是条链,\(O(n)\)的复杂度倍增法O(logn)先预处理下各......
  • P1439 【模板】最长公共子序列
    前置知识:\(LIS\):即最长上升子序列(\(Longest\)\(Increasing\)\(Subsequence\))LuoguB3637最长上升子序列这是一个简单的动规板子题。给出一个由\(n(n\le5000)\)个不超过\(10^6\)的正整数(\(x_1,x_2,\cdots,x_n\))组成的序列。请输出这个序列的最长上升子......
  • (字符串)02-最长公共前缀
    1importjava.util.*;23publicclassSolution{4/**5*@paramstrsstring字符串一维数组6*@returnstring字符串7*/8publicStringlongestCommonPrefix(String[]strs){9//判空数组10if(strs.lengt......
  • 新建一个vite项目,使用ts语法的公共方法库的项目
    要创建一个使用TypeScript语法的公共方法库项目,可以按照以下步骤使用Vite构建工具来设置项目:安装Vite全局工具(如果已安装,请跳过此步骤):npminstall-gcreate-vite```创建新项目:create-vitemy-library--template=ts```上述命令将在名为`my-library`的文件夹中创建......