LCA倍增算法
LCA 算法是一个技巧性很强的算法。
十分感谢月老提供的模板。
这里我实现LCA是通过倍增,其实就是二进制优化。
任何一个数都可以有2的阶数实现
例如16可以由1 2 4 8组合得到
5可以由1 2 4 组合得到
便于读者理解 我放一道例题吧
Problem F: 挑战迷宫
Description
所有房间一共由n-1条路连接,使得房间两两之间能够相互达到(构成一棵树),每条路的长度为Wi。
每当小翔和小明都在房间时,他们的神奇手机就能显示两人的位置(两人分别在哪两个房间),现在想请聪明的ACMer
快速地算出他们之间的最短距离。
Input
接下来n-1行,每行输入3个整数u,v,w(1<=u,v<=n,u!=v,w<=10000),表示编号为u和v的房间之间有一条长为w的路。
第n+1行输入整数m(0<m<=100000),表示有m次询问。
接来下m行,每行输入2个整数u,v(1<=u,v<=n),表示小翔和小明当前所在房间的编号。
Output
Sample Input
4
1 2 1
2 3 1
1 4 1
1
3 4
Sample Output
3 这是CSUST选拔赛的一题,表示当时不会LCA 菜的抠脚 (菜是原罪啊)
注意这题时间为1S N为1e6 最短路肯定是不行的,复杂度不行。
n个点n-1条路 保证联通 其实就是每一个点到另外一个点有唯一的路径。
然后这就是一个非常非常裸的LCA。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector> using namespace std;
#define maxn 100010
struct node {
int x,y;
node(int x=,int y=):x(x),y(y){};
};
int rk[maxn],d[maxn],p[maxn][];
vector<node>a[maxn];
int n;
void dfs(int u,int fa,int cnt) {
rk[u]=cnt;
p[u][]=fa;
int len=a[u].size();
for (int i= ; i<len ; i++) {
int x=a[u][i].x;
if (x!=fa) {
d[x]=d[u]+a[u][i].y;
dfs(x,u,cnt+);
}
}
}
void lca() {
for (int i= ; i<=n ; i++ ) {
for (int j= ; (<<j)<=n ; j++) {
p[i][j]=-;
}
}
for (int j= ; (<<j)<=n ; j++) {
for (int i= ; i<=n ; i++) {
if (p[i][j-]!=-) p[i][j]=p[p[i][j-]][j-];
}
}
}
int query(int x,int y) {
if (rk[x]<rk[y]) swap(x,y );
int k;
for (k= ; (<<(+k))<=rk[x] ; k++);
for (int i= k; i>= ; i--) {
if (rk[x]-(<<i)>=rk[y]) x=p[x][i];
}
if (x==y) return x;
for (int i= k; i>= ; i--) {
if (p[x][i]!=- && p[x][i]!=p[y][i]){
x=p[x][i];
y=p[y][i];
}
}
return p[x][];
}
int main() {
int q,u,v,w;
while(scanf("%d", &n)!=EOF) {
for (int i = ; i < n; i++) {
scanf("%d%d%d", &u, &v, &w);
a[u].push_back(node(v, w));
a[v].push_back(node(u, w));
}
dfs(, -, );
lca();
scanf("%d", &q);
while (q--) {
scanf("%d%d", &u, &v);
printf("%d\n", d[u]+d[v]-*d[query(u, v)]);
}
}
return ;
}
其中DFS(int u,int fa, int cnt)
u表示当前节点 fa为他的父亲节点 cnt代表的是深度;
int rk[maxn]记录深度 d[maxn] 记录节点 p[maxn][30]记录父亲节点的位置
lca() 这个就是精髓所在了 第一步初始化p[i][j]=-1;
第二步就是二进制优化了 p[i][j]=p[p[i][j-1]][j-1] 表示i+2^j=i+2^(j-1)+2^(j-1)
前面都是预处理 第三步query(int x,int y) 求x,y的公共祖先。
先判断深度,然后算出2^k <rk[x] 的k的最大值。
if (rk[x]-(1<<i)>=rk[y]) x=p[x][i];将x的的深度向上回溯2^i
使之更接近rk[y]
for (int i= k; i>=0 ; i--) {
if (p[x][i]!=-1 && p[x][i]!=p[y][i]){
x=p[x][i];
y=p[y][i];
}
}
return p[x][0];
后面就是无脑回溯到公共祖先位置。
非常感谢月老的LCA倍增模板
以上就是我对LCA倍增算法的解析
如果读者还有不懂可以留言给我。
LCA倍增算法的更多相关文章
- 最近公共祖先 LCA 倍增算法
树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...
- POJ 1330 Nearest Common Ancestors (LCA,倍增算法,在线算法)
/* *********************************************** Author :kuangbin Created Time :2013-9-5 9:45:17 F ...
- 算法笔记--lca倍增算法
算法笔记 模板: vector<int>g[N]; vector<int>edge[N]; ][N]; int deep[N]; int h[N]; void dfs(int ...
- LCA倍增算法的错误与模板
先上我原来的错误的代码 type node=^link; link=record num:int64; next:node; end; var fa:..,..] of int64; dep:..] ...
- LCA 倍增算法模板
. #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm&g ...
- LCA(最近公共祖先)之倍增算法
概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介 ...
- LCA(倍增在线算法) codevs 2370 小机房的树
codevs 2370 小机房的树 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 小机房有棵焕狗种的树,树上有N个节点, ...
- Lca 之倍增算法
引入: 比如说要找树上任意两个点的路上的最大值.如果是一般的做法 会 接近o(n)的搜,从一个点搜到另一个点,但是如果询问多了复杂度就很高了. 然后我们会预处理.预处理是o(n²)的,询问是o(1)的 ...
- POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)
1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...
随机推荐
- appium滑动操作(向上、向下、向左、向右)
appium滑动操作(向上滑动.向下滑动.向左滑动.向右滑动) 测试app:今日头条apk 测试设备:夜游神模拟器 代码如下: 先用x.y获取当前的width和height def getSize() ...
- JDBC 基础
JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口 ...
- C# 使用AngleSharp 爬虫图片
AngleSharp 简介 AngleSharp是基于.NET(C#)开发的专门解析HTML源码的DLL组件.根据HTML的DOM结构操作HTML,整个DOM已传输到逻辑类结构中.这种结构可以更好的操 ...
- 算法提高 金陵十三钗 状压DP
思路:深度搜索复杂度N!过不了.考虑动态规划:将已经选择的列记为1,未选择表示0,二进制压缩,例如110,就表示选择了第1列和第2列. d(i, t)表示当前已经匹配了i行,选择了t这些列.状态转移: ...
- JVM笔记3-java内存区域之运行时常量池
1.运行时常量池属于线程共享区中的方法区. 2.运行时常量池用于编译期生成的各种自变量,符号引用,这部分内用将在类加载后接入方法区的运行时常量池中存放. 看如下代码所示,如图: public clas ...
- trigger click 和 click 的区别??
trigger click 和 user click 有什么区别吗? 好像没有的.直到发现了这样一段代码. <button class="btn1">Button< ...
- js中的Object.defineProperty()和defineProperties()详解
ECMAS-262第5版在定义只有内部采用的特性时,提供了描述了属性特征的几种属性.ECMAScript对象中目前存在的属性描述符主要有两种,数据描述符(数据属性)和存取描述符(访问器属性),数据描述 ...
- webpack入门宝典
前提摘要 本文是经过二天自己学习总结出来的一些心得,本文是在最新版的webpack4x的基础上进行配置的(听说webpack4x比以往改变都很大有些插件可能有问题).如果你以前没怎么接触过Webpac ...
- R︱mlr包帮你挑选最适合数据的机器学习模型(分类、回归)+机器学习python和R互查手册
一.R语言的mlr packages install.packages("mlr")之后就可以看到R里面有哪些机器学习算法.在哪个包里面. a<-listLearners() ...
- R+NLP︱text2vec包——BOW词袋模型做监督式情感标注案例(二,情感标注)
要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 在之前的开篇提到了text2vec ...