引入:


比如说要找树上任意两个点的路上的最大值。如果是一般的做法 会 接近o(n)的搜,从一个点搜到另一个点,但是如果询问多了复杂度就很高了。
然后我们会预处理。预处理是o(n²)的,询问是o(1)的,但是n大了,时间会超,内存也开不下。
这个时候就需要lca了。如果是倍增lca的话。处理是o(nlogn的),询问是o(logn)的,你发现什么东西都log一遍就很简单了。。。

lca:


先说下lca。为什么要用lca,打个比方,如果我们事先知道了一个点往上任何一个点是啥,并且到它的路径上的最大值也知道。当询问两个点时,只需要找到他们两往上第一个相同的点(即为lca),然后把他们两往上的值取个最大值,这就是我们的答案。但是这样处理的话,发现空间开不下,如果n大了不可能开一个n²的数组。这时我们需要倍增算法。

倍增:


如果我们提前知道了每个点往上2 ^k的点,那么一个点往上2 ^ (k + 1)的点,即为它往上2 ^ k的点再往上2 ^ k的点(相当于我们借助一个点往上2 ^ k的点为跳板,再往上跳2 ^ k,即可到达一个点往上2 ^ (k + 1)的点)这样每次寻找一个点往上任何高度的点变为了 log;
 
就这样维护一遍就可以求了
 

贴上自己yy的代码:


#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N = 4e4;
const int M = 4e5;
using namespace std;
int h[N],cnt,gra[N][],dep[N];
int maxn[N][],n,m;
struct path{
int next,to;
int dis;
}e[M];
void add(int u,int v,int dis){
e[++cnt].to = v;
e[cnt].next = h[u];
e[cnt].dis = dis;
h[u] = cnt;
}
void dfs(int u,int pre){
for(int i = h[u];i;i = e[i].next){
int v = e[i].to;
if(v == pre)continue;
gra[v][] = u;//处理出每个点的直接父亲
maxn[v][] = e[i].dis;//处理出每个点到直接父亲的距离
dep[v] = dep[u] + ;
dfs(v,u);
}
}
int LCA(int x,int y){
if(dep[x] < dep[y])swap(x,y);
int flag = false;
int log;
for(log = ;( << log) <= dep[x];log++);log--;
int ans = ;
for(int i = log;i >= ;i--)
if(dep[x] - ( << i) >= dep[y]){
ans = max(ans,maxn[x][i]);
x = gra[x][i];
}//把x向上移到和y相同高度
if(x == y)return ans;//如果y就是lca 直接跳出
for(int i = log;i >= ;i--){
if(gra[x][i] && gra[y][i] != gra[x][i]){
ans = max(ans,maxn[x][i]);x = gra[x][i];
ans = max(ans,maxn[y][i]);y = gra[y][i];
}
}//把x 和 y同时向上移,如果相同,即找到lca
if(gra[x][])ans = max(ans,maxn[x][]);
if(gra[y][])ans = max(ans,maxn[y][]);
if(!gra[x][] && x != y)return -;//如果移到根节点且x != y即x,y不在一颗树上返回-1
return ans;
}
void getMap(){
scanf("%d %d",&m,&n);
int a,b,z;
for(int i = ;i <= n;i++){
scanf("%d %d %d",&a,&b,&z);
add(a,b,z);
add(b,a,z);
}
for(int i = ;i <= m;i++){
if(!dep[i]){
dep[i] = ;
dfs(i,-);
}
}
for(int j = ;( << j) <= m;j++)
for(int i = ;i <= m;i++)
if(gra[i][j - ]){
int a = gra[i][j - ];
gra[i][j] = gra[a][j - ];
maxn[i][j] = max(maxn[i][j - ],maxn[a][j - ]);
}//处理出每个点1 - 2^k的父亲,和路上最大边权;
}
int main(){
getMap();
return ;
}

  

 

Lca 之倍增算法的更多相关文章

  1. LCA的倍增算法

    LCA,即树上两点之间的公共祖先,求这样一个公共祖先有很多种方法: 暴力向上:O(n) 每次将深度大的点往上移动,直至二者相遇 树剖:O(logn) 在O(2n)预处理重链之后,每次就将深度大的沿重链 ...

  2. 关于树论【LCA树上倍增算法】

    补了一发LCA,表示这东西表面上好像简单,但是细节真挺多. 我学的是树上倍增,倍增思想很有趣~~(爸爸的爸爸叫奶奶.偶不,爷爷)有一个跟st表非常类似的东西,f[i][j]表示j的第2^i的祖先,就是 ...

  3. LCA(最近公共祖先)之倍增算法

    概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介 ...

  4. LCA倍增算法

    LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...

  5. 最近公共祖先 LCA 倍增算法

          树上倍增求LCA LCA指的是最近公共祖先(Least Common Ancestors),如下图所示: 4和5的LCA就是2 那怎么求呢?最粗暴的方法就是先dfs一次,处理出每个点的深度 ...

  6. 关于LCA的倍增解法的笔记

    emmmmm近日刚刚学习了LCA的倍增做法,写一篇BLOG来加强一下印象w 首先 何为LCA? LCA“光辉”是印度斯坦航空公司(HAL)为满足印度空军需要研制的单座单发轻型全天候超音速战斗攻击机,主 ...

  7. [模板]LCA的倍增求法解析

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  8. 【一个蒟蒻的挣扎】LCA (倍增)

    #include<cstdio> #include<iostream> #include<cstring> using namespace std; struct ...

  9. LCA树上倍增求法

    1.LCA LCA就是最近公共祖先(Least common ancestor),x,y的LCA记为z=LCA(x,y),满足z是x,y的公共祖先中深度最大的那一个(即离他们最近的那一个)qwq 2. ...

随机推荐

  1. 洛谷 P2319 [HNOI2006]超级英雄

    题目描述 题目描述 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金.主持人问题准备了若干道题目,只有当选手正确回答一 ...

  2. 分享一个开源的JavaScript统计图表库,40行代码实现专业统计图表

    提升程序员工作效率的工具/技巧推荐系列 推荐一个功能强大的文件搜索工具SearchMyFiles 介绍一个好用的免费流程图和UML绘制软件-Diagram Designer 介绍Windows任务管理 ...

  3. SEO 第七章

    SEO第七章 网站网址链接 路径优化 网站的网址路径分为相对路径和绝对路径 绝对路径:绝对路径是完整的路径,不仅可以在站内打开,去其他地方依然可以打开. 相对路径:不是一个完整的路径,这种路径只能在站 ...

  4. javaee 第五周作业

    一.Ajax技术 AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). AJAX 不是新的编程语言,而是一种使用现有标准的新方法. ...

  5. css3 calc()属性介绍以及自适应布局使用方法

    前端知识 Calc()介绍 calc的英文是calculate的缩写,中文为计算的意思,是css3的一个新增的功能,用来只当元素的长度.比如说:你可以用calc()给元素margin.padding. ...

  6. uva1412 Fund Management

    状压dp 要再看看  例题9-17 /* // UVa1412 Fund Management // 本程序会超时,只是用来示范用编码/解码的方法编写复杂状态动态规划的方法 // Rujia Liu ...

  7. js中数组删除 splice和delete的区别,以及delete的使用

    var test=[];test[1]={name:'1',age:1};test[2]={name:'2',age:2};test[4]={name:'3',age:3}; console.log( ...

  8. DI:Defect Index(缺陷率)

    DI:Defect Index(缺陷率) 定义:DI值是衡量软件质量的高低的指标之一. 公式:DI= 致命级别的问题个数*10+严重级别的问题个数*3+一般级别的问题个数*1+提示级别的问题个数*0. ...

  9. check.pl

    比对两个文件并纠错 #!/usr/bin/perl use strict; use warnings; ###############################################m ...

  10. es6(三set和map数据结构)

    es6中提供了一个新的数据结构Set,他有点类似数组,但和数组不同的是,在里面你如果写入重复的值的话,他不会显示重复值. const s =new Set(); [2,3,4,5,6,6,6,7,8, ...