2016.1.28

LCA,就是最近公共祖先,这里介绍倍增的算法。

首先我们要预处理,设f[i][j]为编号为i的节点的2j级祖先,所谓2j级祖先,就是从i节点开始往树的上层数2j个节点。如下图所示

编号是乱编的。。。

节点11的20级祖先就是他爹10号节点,节点11的21级祖先就是8号节点,节点11的22级祖先就是6号节点。

这样我们就有递归式:f[i][j]=f[ f[i][j-1] ][ j-1 ],i号节点的2j级祖先就是i号节点的2j-1级祖先的2j-1级祖先。

这件事情我们可以通过从根节点进行一次dfs来完成,在递归之前处理当前结点的祖先即可。

代码如下:

void LCA(int x)
{
vis[x]=;
for(int i=;(<<i)<=dep[x];i++)
{
int c=f[x][i-];//c为x的2^i-1级祖先
f[x][i]=f[c][i-];//f[x][i]赋值为c的2^i-1级祖先
}
for(int i=final[x];i;i=last[i])
{
if(!vis[to[i]])
{
dep[to[i]]=dep[x]+;//更新深度
f[to[i]][]=x;//更新该边到达节点的2^0级祖先
LCA(to[i]);
}
}
}

然后,我们对于询问的节点a和b的最近公共祖先,开始倍增。具体操作如下:(假设在11号和3号节点各站了一个小人a和b)

1、让深度较大的节点(假设是上图11号节点)上的小人沿着边一直向上层跳到和深度较小的节点(假设是上图3号节点)同一深度。(也就是a跳到8号节点)

2、a和b同时开始倍增,如果倍增之后两人所在位置不同,即执行倍增,否则,减小倍增的倍数(假设倍增2k后发现两人在同一位置了,则尝试倍增2k-1)。

3、重复执行操作2,直到无法继续执行。

4、现在,a一定6号节点,b一定在18号节点。换句话说,a和b一定在他俩lca的下一层。

5、a和b往上跳一层便是他俩的lca了

这段操作并不好理解,对着代码看就好了:

int query(int a,int b)
{
if(dep[a]<dep[b]) swap(a,b);
for(int i = maxlog ; i >= ; i-- ) //2^maxlog是这棵树的最大可能深度,从大级别往小级别倍增,直到a跳到与b同深度
if(dep[a]-(<<i)>=dep[b])
a=f[a][i];
if(a==b) return b;//注意特判,b可能就是他俩的lca
for(int i = maxlog ; i >= ; i-- ) //a和b同时开始往上倍增
if(dep[a] > (<<i) && f[a][i] != f[b][i])
{
a=f[a][i];
b=f[b][i];
}
//此时a和b的上一层就是lca
return f[a][];
}

然后再来看题:NOIP201307货车运输

BZOJ 3732 Network

LCA的更多相关文章

  1. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  2. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  3. [bzoj3123][sdoi2013森林] (树上主席树+lca+并查集启发式合并+暴力重构森林)

    Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数 ...

  4. [bzoj2588][count on a tree] (主席树+lca)

    Description 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权.其中lastans是上一个询问的答案,初始 ...

  5. [板子]倍增LCA

    倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...

  6. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  7. [bzoj3626][LNOI2014]LCA

    Description 给出一个$n$个节点的有根树(编号为$0$到$n-1$,根节点为$0$). 一个点的深度定义为这个节点到根的距离$+1$. 设$dep[i]$表示点$i$的深度,$lca(i, ...

  8. (RMQ版)LCA注意要点

    inline int lca(int x,int y){ if(x>y) swap(x,y); ]][x]]<h[rmq[log[y-x+]][y-near[y-x+]+]])? rmq[ ...

  9. bzoj3631: [JLOI2014]松鼠的新家(LCA+差分)

    题目大意:一棵树,以一定顺序走完n个点,求每个点经过多少遍 可以树链剖分,也可以直接在树上做差分序列的标记 后者打起来更舒适一点.. 具体实现: 先求x,y的lca,且dep[x]<dep[y] ...

  10. 在线倍增法求LCA专题

    1.cojs 186. [USACO Oct08] 牧场旅行 ★★   输入文件:pwalk.in   输出文件:pwalk.out   简单对比时间限制:1 s   内存限制:128 MB n个被自 ...

随机推荐

  1. Android 性能测试

    写在前面: 测试一道,博主接触的也是皮毛而已,没有接触过rom的测试,下边所说的都是博主接触过的app的性能测试.我只谈方法,少提概念.各位大神不喜勿喷. 概述 除启动时间外,我们应该做的测试,可能需 ...

  2. C#编程语言与面向对象——委托

    委托(delegate)也可以看成是一种数据类型,可以用于定义变量,但它是一种特殊的数据类型,所定义的变量能接收的数值只能是个函数,更确切地说,委托类型的变量可以接收一个函数的地址. 简单地说 委托变 ...

  3. Codeforces Round #379 (Div. 2) A B C D 水 二分 模拟

    A. Anton and Danik time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  4. 杭电acm 1002 大数模板(一)

    从杭电第一题开始A,发现做到1002就不会了,经过几天时间终于A出来了,顺便整理了一下关于大数的东西 其实这是刘汝佳老师在<算法竞赛 经典入门 第二版> 中所讲的模板,代码原封不动写上的, ...

  5. Surprise团队第二周项目总结

    Surprise团队第二周项目总结 项目进展 已实现五子棋人人模式部分 人人模式: 基本方式:采取黑棋先行,黑白交替的下棋顺序. 模式:通过鼠标点击相应棋盘中的"交叉点",在lay ...

  6. Linux指令小结

    1.apt指令集:是ubuntu中最强大的命令行软件管理工具,用于获取.安装.编译.卸载和查询软件包.还可以检查软件包的依赖关系.在ubunt中下载是根据/etc/apt/sources.list这个 ...

  7. python线程池(threadpool)模块使用笔记

    一.安装与简介 pip install threadpool pool = ThreadPool(poolsize) requests = makeRequests(some_callable, li ...

  8. 第三篇T语言实例开发,图色操作

    ---恢复内容开始--- 图色的基本操作 1.找颜色色命令的基本操作 坐标点取色:获取指定坐标点的颜色 区域找色:在指定区域里找某一个颜色 模糊找色:在指定区域里找某一个颜色,可以设置相似度 多点找色 ...

  9. iOS 传值 委托(delegate)和block 对比

     技术交流新QQ群:414971585 这篇文章建议和前一篇一起看, 另外先弄清楚IOS的block是神马东东. 委托和block是IOS上实现回调的两种机制.Block基本可以代替委托的功能,而且实 ...

  10. 2016HUAS_ACM暑假集训4D - 计数,排列

    一个错排公式的基础应用. 大致题意:求n个数的错误排列方式.(每个都要错) 在这里先贴一下错排公式:D(1)=0:D(2)=1:D(n)=(n-1)*(D(n-1)+D(n-2)) 它的推导也非常有意 ...