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 ...
随机推荐
- 将Word表格中单元格中的文字替换成对应的图片
示例 原文件结构: 替换后文档结构: 软件截图: 代码: using System;using System.Collections.Generic;using System.ComponentMod ...
- Spring mvc学习指南
使用flash attribute(闪存传值) 在配置文件中添加<mvc:annotion-driven/> 在controller方法参数里面添加RedirectAttributes r ...
- java12 - 正则表达式
正则表达式简介 常用搭配说明: ^a 表示这个位置只能是字母 a [1,2,3,4] 表示这个位置只能在 1,2,3,4 中取一个 [[a-z][A-Z]] 表示可以任意大小写字母 ([a-z]{1, ...
- python——Django项目模板
views.py # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts impor ...
- C语言老司机学Python (一)
Python 版本:3.6.4 参考网上教程:http://www.runoob.com/python3/python3-basic-syntax.html 开始了啊. 干咱们这行的老规矩,学新语言的 ...
- HttpURLConnection发送请求
每个 HttpURLConnection 实例都可用于生成单个请求,但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络.请求后在 HttpURLConnection 的 InputStrea ...
- "No Python interpreter configured for the project " in Pycharm for python selenium
自动化测试问题: pyCharm提示python Interpreter没有设置,点击configure Python Interpreter,进入Settings 在 Project Interpr ...
- VC6安装错误——Error Launching acmboot.exe
因项目需要,我需要安装Microsoft Visual C++ Professional Version 6 SP5.但是在安装时运行安装目录下的setup.exe,出现Error Launching ...
- 【php】strtr与str_replace的区别
strtr(string,from,to): 逐个字符开始替换,以from跟to中长度较较短的一个为准,例如: strtr("aidenliu","ai",&q ...
- Flex中的FusionCharts 3D柱形图
1.3D柱形图源码 <?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:f ...