与正文无瓜的前言

身为一个高一才开始学的OIER,现在才开始恶补模板,感觉今年就要退役了。

不想刷题了滚过来写写博客<-------极端危险的思想。

引入

LCA(Lowest Common Ancestors),即最近公共祖先,听名字就知道这是与树上两个节点有关的东西。

它的定义就是两个点最近的公共祖先(废话),同时它也是树上一个节点到另一个节点的最短路中经过的深度最小的点。

如图,2就是8与9的最近公共祖先,7就是10和12的最近公共祖先。

那么LCA有什么用呢?

举个例子,我们可以利用LCA在O(1)的时间复杂度内求出树上两点u,v的最短距离。这里用dep表示节点的深度。

dis(u,v)=dep(u)+dep(v)-2*dep(LCA(u,v));

所以能快速求出LCA就可以快速求出两点间的距离。当然LCA还有其它作用,这里就不再赘述了(其实我并不知道)。

正文

我们来想一下一般的LCA求法。

对于任意两个节点u,v,如果我们一开始让它们同时向上寻找祖先,因为它们深度可能不同,其中深度较低的点就会向上走过头。

就像这样:

所以我们先让深度较深的点先向上走,走到与另一个点深度相同时,两个点再肩并肩向上走,找到第一个公共祖先为止。

而用倍增求LCA的方法也跟这个差不多,只不过不是一步一步向上走,而是先预处理出每个点向上走2^k步到达的节点,再向上飞。

设fa[i][j]为i节点向上走2^j步到达的节点,那么fa[i][j]可以这么转移:fa[i][j]=fa[ fa[i][j-1] ][j-1]转移过来。

这里介绍两种预处理的方式。

一种是一边遍历树一边处理,代码如下:

void dfs(int x,int f)
{
dep[x]=dep[fa[x][]=f]+;
for(int j=;j<=;j++)
fa[x][j]=fa[fa[x][j-]][j-];
for(int i=info[x];i;i=nex[i])if(v[i]!=f)dfs(v[i],x);
}

另一种是先遍历,然后处理,代码:

 void dfs(int x,int f)
{
dep[x]=dep[fa[x][]=f]+;
for(int i=info[x];i;i=nex[i])if(v[i]!=f)dfs(v[i],x);
}
void pre()
{
dfs(,);
for(int j=;j<=LOG;j++)for(int i=;i<=n;i++)
fa[i][j]=fa[fa[i][j-]][j-];
}

预处理完后,我们就可以让深度较深的节点快速的与另一个节点会和,然后比翼双飞

直接给出代码和注解:

int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int delta=dep[x]-dep[y];
for(int i=LOG;i>=;i--)
if(delta&(<<i))x=fa[x][i];//将delta转化为二进制,再用2^i凑出来
if(x==y)return x;
for(int i=LOG;i>=;i--)//用2^i凑距离,对于每个2^i只有可能被用一次,从大到小就是为了防止多用。
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];//如果相等就一起向上飞,会飞到公共祖先,但不是最近的
return fa[x][];
}

树——倍增LCA的更多相关文章

  1. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  2. 洛谷P4180 [BJWC2010]次小生成树(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  3. 树上第k小,可持久化线段树+倍增lca

    给定一颗树,树的每个结点都有权值, 有q个询问,每个询问是 u v k ,表示u到v路径上第k小的权值是多少. 每个结点所表示的线段树,是父亲结点的线段树添加该结点的权值之后形成的新的线段树 c[ro ...

  4. 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并

    [BZOJ3123][Sdoi2013]森林 Description Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整 ...

  5. bzoj 3123 [Sdoi2013]森林(主席树,lca,启发式合并)

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

  6. Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

    题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB    总提交次数:196   AC次数:65   平均分: ...

  7. 洛谷P2633 Count on a tree(主席树,倍增LCA)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

  8. 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)

    洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...

  9. 洛谷P2633 Count on a tree(主席树,倍增LCA,树上差分)

    洛谷题目传送门 题目大意 就是给你一棵树,每个点都有点权,每次任意询问两点间路径上点权第k小的值(强制在线). 思路分析 第k小......又是主席树了.但这次变成树了,无法直接维护前缀和. 又是树上 ...

随机推荐

  1. 【洛谷 P3224】 [HNOI2012]永无乡(Splay,启发式合并)

    题目链接 启发式合并就是暴力合并把小的合并到大的里,一个一个插进去. 并查集维护连通性,同时保证并查集的根就是所在Splay的根,这样能省去很多操作. #include <cstdio> ...

  2. stage1----航空票务系统需求分析报告

    航空票务管理系统需求分析报告 题    目    航空票务管理系统需求分析报告 学    院       信息科学与工程学院 专    业        计算机科学与技术 组    员         ...

  3. el-pagination分页优化

    表格分页优化: <template> <el-pagination small background @size-change="handleSizeChange" ...

  4. wireshark语法小结

    https://blog.csdn.net/cumirror/article/details/7054496 过滤重传包 https://blog.csdn.net/Joseph_ChiRunning ...

  5. Win10 C盘 系统和保留 占用空间 非常大

    Win10 C盘 系统和保留 占用空间 非常大今天在写代码的时候,突然发现Redis起不来了,一看原因,是因为C盘空间不足.然后,我看了下C盘,发现...一个叫系统和保留的东西,居然占了110G的空间 ...

  6. 利用 Create React Native App 创建 React Native 应用

    $ npm i -g create-react-native-app $ create-react-native-app my-project $ cd my-project $ npm start

  7. Vue过渡效果的实现

    1.Vue 过渡组件 Vue 在插入.更新或者移除 DOM 时,使用内置的过渡封装组件可以实现过渡效果 语法格式: <transition name = "xx"> & ...

  8. 零基础Python教程-详说list有序集合

    list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出你周围同事的名字,就可以用一个list表示: >>> classmates = ['Michael', 'Bob' ...

  9. python多线程扫描爆破网站服务器思路【笔记】

    这个扫描是概率问题,是需要字典的,以下代码是作为参考,字典可以去网上下载,我就不提供,我提供的是思路! #!/usr/bin/env python # coding=utf-8   from IPy ...

  10. 关于Bigdecimal的问题

    Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数.在实际应用中,需要对更大或者更小的数进行 ...