【数据结构】浅谈倍增求LCA
思路
运用树上倍增法可以高效率地求出两点x,y的公共祖先LCA
我们设f[x][k]表示x的2k辈祖先
f[x][0]为x的父节点
因为从x向根节点走2k 可以看成从x走2k-1步 再走2k-1步
所以对于1≤k≤logn 有f[x][k]=f[f[x][k-1]][k-1] (类似二分思想)
预处理:
因此我们可以对树进行遍历后得到所有f[x][0] 再计算出f数组的所有值
求LCA:
设dep[x]为x的深度 设dep[x]≥dep[y](否则 可以交换x和y)
使用二进制拆分 把x和y调整到同一深度
若此时x与y相等 则已经找到LCA
若不相等 则x和y同时向上跳同一深度 直到他们的父节点相同 则他们的父节点就是LCA
代码
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
#define maxn 500050
#define INF 1e9+7
int n,m,cnt,ans,a,b,k,x,y;
int h[maxn],dep[maxn],f[maxn][];
struct Edge
{
int next;
int to;
}e[maxn<<];
void add(int u,int v)
{
e[++cnt].to=v;
e[cnt].next=h[u];
h[u]=cnt;
}
void deal(int u,int fa)
{
dep[u]=dep[fa]+;//子节点深度等于父节点+1
for(int i=;i<=;i++)
{
f[u][i]=f[f[u][i-]][i-];//计算u的2^k辈祖先
}
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa) continue;//如果是父节点就退出
f[v][]=u;//v是u的子节点
deal(v,u);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);//如果x的深度比y小 就交换
for(int i=;i>=;i--)//从大到小循环 先走大步 如果不行在走小步
{
if(dep[f[x][i]]>=dep[y]) x=f[x][i];//当走完深度还是大于y 就走
if(x==y) return x;//当x=y时 找到LCA
}
for(int i=;i>=;i--)//此时x和y已经在同一层了
{
if(f[x][i]!=f[y][i])//如果往上走之后还没有到LCA 就往上走
{
x=f[x][i];
y=f[y][i];
}
}
return f[x][];//返回LCA
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);//无向图
}
deal(,);//预处理
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}
【数据结构】浅谈倍增求LCA的更多相关文章
- 树上倍增求LCA(最近公共祖先)
前几天做faebdc学长出的模拟题,第三题最后要倍增来优化,在学长的讲解下,尝试的学习和编了一下倍增求LCA(我能说我其他方法也大会吗?..) 倍增求LCA: father[i][j]表示节点i往上跳 ...
- [算法]树上倍增求LCA
LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 然后把深度更深的那一个点(4 ...
- 【倍增】洛谷P3379 倍增求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- hdu 2586 How far away ? 倍增求LCA
倍增求LCA LCA函数返回(u,v)两点的最近公共祖先 #include <bits/stdc++.h> using namespace std; *; struct node { in ...
- 倍增求lca模板
倍增求lca模板 https://www.luogu.org/problem/show?pid=3379 #include<cstdio> #include<iostream> ...
- 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)
洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...
- 倍增求LCA学习笔记(洛谷 P3379 【模板】最近公共祖先(LCA))
倍增求\(LCA\) 倍增基础 从字面意思理解,倍增就是"成倍增长". 一般地,此处的增长并非线性地翻倍,而是在预处理时处理长度为\(2^n(n\in \mathbb{N}^+)\ ...
- 树链剖分与倍增求LCA
树链剖分与倍增求\(LCA\) 首先我要吐槽机房的辣基供电情况,我之前写了一上午,马上就要完成的时候突然停电,然后\(GG\)成了送链剖分 其次,我没歧视\(tarjan LCA\) 1.倍增求\(L ...
- [学习笔记] 树上倍增求LCA
倍增这种东西,听起来挺高级,其实功能还没有线段树强大.线段树支持修改.查询,而倍增却不能支持修改,但是代码比线段树简单得多,而且当倍增这种思想被应用到树上时,它的价值就跟坐火箭一样,噌噌噌地往上涨. ...
随机推荐
- Be opinionated out of the box but get out of the way quickly as requirements start to diverge from
Be opinionated out of the box but get out of the way quickly as requirements start to diverge from t ...
- 基于easyUI实现权限管理系统(二)——菜单导航
此文章是基于 EasyUI+Knockout实现经典表单的查看.编辑 一. 相关文件介绍 1. menu.jsp:菜单导航主界面 <!DOCTYPE html PUBLIC "-//W ...
- jquery not() 方法
1.not(expression) 根据表达式参数的值,从包装集里删除元素 example : $('img[alt]').not('[alt*=joy]') 返回包含属性alt的img元素,但img ...
- ActiveX界面已显示,调用方法报undefined的处理办法
1.在ie中将当前网址加入信任网站 2.设置->internet选项->安全->受信任站点->自定义级别:将所有有关ActiveX的选项设置为启用 3.重启ie再次访问即可. ...
- Sass初入门
什么是CSS预处理器? CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行编码工作. 什 ...
- windows 打印刻录 代码规范及问题
1.获取CString字节数 int z_Len = WideCharToMultiByte(CP_ACP, 0, z_FileXml.GetBuffer(), z_FileXml.GetLength ...
- Oracle基础之Merge into
Merge into语句是Oracle9i新增的语法,用来合并UPDATE和INSERT语句. 通过MERGE语句,根据一张表或多表联合查询的连接条件对另外一张表进行查询,连接条件匹配上的进行UPDA ...
- Charles下载和使用
下文作为备份.来源:https://www.cnblogs.com/rrl92/p/7928770.html 1. Charles下载地址 地址:https://www.charlesproxy.co ...
- UVaOJ 694 - The Collatz Sequence
题目很简单,但是一开始却得到了Time Limit的结果,让人感到很诧异.仔细阅读发现,题目中有一个说明: Neither of these, A or L, is larger than 2,147 ...
- Python 爬虫 根据属性值关键字搜索标签
# <div class='\"name\"'>客如云</div> company_name = soup.find_all('div',class_=re ...