两个最近的点u和v的最近的公共的祖先称为最近公共祖先(LCA)。普通的LCA算法,每算一次LCA的时间复杂度为线性o(n);

这里讲LCA + 二分的方法。首先对于任意的节点v,利用其父节点的信息,可以通过par2[v]=par[par[v]]得到向上走两步的节点。依此信息可以通过par4[v]=par2[par2[v]]得到向上走4步的节点。所以,根据此方法可以得到向上走2^k所得到的节点par[k][v]。每次搜索的复杂度为o(log n),预处理par[k][v]的复杂度为o(nlog n)。(我觉得挑战程序设计LCA部分写的挺明白的)

模版代码如下:

 //LCA + 二分

 vector <int> G[MAX_V]; //邻接表
int root; //根的编号 int par[MAX_LOG_V][MAX_V]; // 向上走2^k所到的父节点编号(根节点的父节点为-1)
int dep[MAX_V]; //节点的深度 void dfs(int v , int p , int d) { //3个参数分别表示 当前节点 父节点 深度
par[v][] = p;
dep[v] = d;
for(int i = ; i < G[v].size() ; i++) {
dfs(G[v][i] , v , d + );
}
}
//预处理
void init(int n) {
dfs(root , - , ); //预处理出par[0]和dep
for(int k = ; k + < MAX_LOG_V ; k++) {
for(int v = ; v <= n ; v++) {
if(par[k][v] < )
par[k + ][v] = -; //v向上的2 ^ (k + 1)的节点超过根节点
else
par[k + ][v] = par[k][par[k][v]]; //v向上的2^k的节点 又向上的2^k个节点,所以是向上2^(k + 1)个节点
}
}
}
//计算u和v的LCA
int lca(int u , int v) {
if(dep[u] < dep[v]) //让u和v向上走到同一深度
swap(u , v);
for(int k = ; k < MAX_LOG_V ; k++) {
if((dep[v] - dep[u]) >> k & ) { //把深度差化为2进制(快速幂原理) 依次从低位相减
v = par[k][v];
}
}
if(u == v) //要是节点相同则输出LCA
return u;
for(int k = MAX_LOG_V - ; k >= ; k--) { //二分搜索计算LCA
if(par[k][u] != par[k][v]) { //若他们的2^k节点不相同 则u和v向上移动,一直移动直到他们的上一个节点相同
u = par[k][u];
v = par[k][v];
}
}
return par[][u];
}

LCA + 二分(倍增)的更多相关文章

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

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

  2. LCA的倍增算法

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

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

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

  4. 【bzoj2280】[Poi2011]Plot 二分+倍增+二分+最小圆覆盖

    题目描述 给出一系列点p_1, p_2, ... , p_n,将其分成不多余m个连续的段,第i段内求一个点q_i,使得q_i到这段内点的距离的最大值的最大值最小 输入 第一行,n m下面n行,每行两个 ...

  5. noip 2015 运输计划 (lca+二分)

    /* 95 最后一个点T了 qian lv ji qiong 了 没学过树剖 听chx听xzc说的神奇的方法 Orz 首先求出每个计划的路径长度 这里写的倍增 然后二分答案 对于每个ans 统计> ...

  6. BZOJ2144跳跳棋——LCA+二分

    题目描述 跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子.我们用跳跳棋来做一个简单的 游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.我们要通过最少的跳动把他们的位置移动 ...

  7. bzoj2144: 跳跳棋(二分/倍增)

    思维好题! 可以发现如果中间的点要跳到两边有两种情况,两边的点要跳到中间最多只有一种情况. 我们用一个节点表示一种状态,那么两边跳到中间的状态就是当前点的父亲,中间的点跳到两边的状态就是这个点的两个儿 ...

  8. [luoguP2680] 运输计划(lca + 二分 + 差分)

    传送门 暴力做法 50 ~ 60 枚举删边,求最大路径长度的最小值. 其中最大路径长度运用到了lca 我们发现,求lca的过程已经不能优化了,那么看看枚举删边的过程能不能优化. 先把边按照权值排序,然 ...

  9. LCA树上倍增求法

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

随机推荐

  1. gulp自动刷新插件

    gulp自动刷新的插件很多,但是感觉最好用的还是 browser-sync 插件.如果不想用命令行,也可以使用 browser-sync界面工具 先安装 browser-sync 插件: npm in ...

  2. [LeetCode#267] Palindrome Permutation II

    Problem: Given a string s, return all the palindromic permutations (without duplicates) of it. Retur ...

  3. zoj 3778 Talented Chef(思维题)

    题目 题意:一个人可以在一分钟同时进行m道菜的一个步骤,共有n道菜,每道菜各有xi个步骤,求做完的最短时间. 思路:一道很水的思维题, 根本不需要去 考虑模拟过程 以及先做那道菜(比赛的时候就是这么考 ...

  4. linux中改变文件权限和属性

    Linux中,默认显示所有用户名的文件在/etc/passwd,用户组的信息在/etc/group 密码/etc/shadow chgrp改变文件所属用户组 chgrp [-R] 用户组名 文件或目录 ...

  5. org.tigris.subversion.javahl.ClientException: Attempted to lock an already-locked dir异常解决方法

    myeclipse用svn提交的时候报错: Attempted to lock an already-locked dir svn: Working copy 'D:/Program Files/My ...

  6. 终极解决方案:windows10开机黑屏,死机

    windows10开机黑屏,死机一般情况都是由于双显卡中的独立显卡驱动造成的! 那么试着升级一下你的BIOS吧!一定要在官网下载你对应的BIOS驱动,然后双击安装,这个时候就别再动机子了,让他自己刷新 ...

  7. BZOJ 1610 连线游戏

    BZOJ不允许除以0. #include<iostream> #include<cstdio> #include<cstring> #include<cstd ...

  8. AngularJS promise()

    实例说明一 <!DOCTYPE html> <html ng-app="my-app"> <head> <meta charset=&qu ...

  9. NavieBayes中的多项式与伯努力模型

    1文本分类过程 例如文档:Good good study Day day up可以用一个文本特征向量来表示,x=(Good, good, study, Day, day , up).在文本分类中,假设 ...

  10. 常用的css的技巧

    1.在做项目当中,由静态页面来载入到项目中,作为动态数据的部分,若是这个动态数据,前面或者后面有需要图片显示(图片是用background来显示的),一般不用float:left或者right,而是p ...