参考博客:https://blog.csdn.net/my_sunshine26/article/details/72717112

首先看一下定义,来自于百度百科

  LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先。

注意:这里某个节点本身也是它的祖先节点。

求最近公共祖先的算法:

1、暴力:每次查询的时间复杂度为O(N)

2、Tarjan(离线)算法:在一次遍历中把所有查询解决,预处理时间复杂度O(nlogn),每次查询时间复杂度O(1),总时间复杂度是O(nlogn+q)

3、倍增算法:利用二分两个节点同时往上走,直到相遇,预处理时间复杂度O(nlogn),每次查询时间复杂度O(logn)

Tarjan(离线)算法

一.Tarjan算法大致实现过程

  1. 先选择一个节点u为根节点,从根节点开始搜索。(标记u已访问过)
  2. 遍历该点u的所有儿子节点v,并标记v已访问过。
  3. 若v还有儿子节点,对v重复ii操作,否则进入下一操作。
  4. 把v合并到u上(并查集)。
  5. 把当前的点设为u,遍历与u有询问关系的节点v。
  6. 如果v在之前已经被访问过,那么u和v的最近公共祖先就是v通过并查集合并后的父亲节点(注意是合并后),即当前的find(v)。
 
 

二.Tarjan算法的伪代码

  

 Tarjan(u)           //根节点u
{
for each(u,v)
{
Tarjan(v); //v还有儿子节点
join(u,v); //把v合并到u上
vis[v]=; //访问标记
}
for each(u,v) //遍历与u有询问关系的节点v
{
if(vis[v])
{
ans=find(v);
}
}
}

三.Tarjan算法的代码

 void Tarjan(int u)
{
vis[u]=;
for(int i=;i<mp[u].size();i++)
{
int v=mp[u][i];
if(vis[v]==)
{
Tarjan(v);
join(u,v);
}
}
for(int i=;i<mp2[u].size();i++)//利用mp2集合来存储查询关系
{
int v=mp2[u][i];
if(vis[v]==)
{
lca[u][v]=find(v);
}
}
}

倍增算法

一、算法铺垫

首先让u和v中较深的一个往上走|depth(u)-depth(v)|步,然后再一起一步步往上走,直到走到同一个节点,就可以在O(depth(u)+depth(v))的时间内求出LCA。

关键在于如何优化向上查找的过程

二.倍增算法的实现过程

分析刚才的算法,两个节点到达同一节点后,不论怎么向上走,达到的显然还是同一节点。利用这一点,我们就能够利用二分搜索求出到达最近公共祖先的最小步数了。

首先我们要进行预处理。对于任意的节点,可以通过fa2[v]=fa[fa[v]]得到其向上走2步到达的顶点,再利用这个信息,又可以通过fa4[v]=fa2[fa2[v]]得到其向上走4步所到的顶点。以此类推,我们可以得到其向上走2^k步所到的顶点fa[v][k],预处理的时间点复杂度为O(nlogn)。

 void init()
{
lg[]=;
for(int i=;i<=n;i++)
lg[i]=lg[i-]+(<<(lg[i-]+)==i);//用来求log2(n)
}
void dfs(int f,int fath)
{
deepth[f]=deepth[fath]+;
fa[f][]=fath;
for(int i=;(<<i)<=deepth[f];i++)
fa[f][i]=fa[fa[f][i-]][i-];
for(int i=;i<mp[f].size();i++)
if(mp[f][i]!=fath)
dfs(mp[f][i],f);
}
int lca(int x,int y)
{
if(deepth[x]<deepth[y])
swap(x,y);
while(deepth[x]>deepth[y])
x=fa[x][lg[deepth[x]-deepth[y]]];
if(x==y)
return x;
for(ll k=lg[deepth[x]];k>=;k--)
if(fa[x][k]!=fa[y][k])
x=fa[x][k], y=fa[y][k];
return fa[x][];
}
 

LCA(最近公共祖先)算法的更多相关文章

  1. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)

    Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...

  2. LCA近期公共祖先

    LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...

  3. LCA 近期公共祖先 小结

    LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...

  4. lca 最近公共祖先

    http://poj.org/problem?id=1330 #include<cstdio> #include<cstring> #include<algorithm& ...

  5. LCA(最近公共祖先)模板

    Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...

  6. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  7. LCA最近公共祖先 ST+RMQ在线算法

    对于一类题目,是一棵树或者森林,有多次查询,求2点间的距离,可以用LCA来解决.     这一类的问题有2中解决方法.第一种就是tarjan的离线算法,还有一中是基于ST算法的在线算法.复杂度都是O( ...

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

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

  9. LCA最近公共祖先(Tarjan离线算法)

    这篇博客对Tarjan算法的原理和过程模拟的很详细. 转载大佬的博客https://www.cnblogs.com/JVxie/p/4854719.html 第二次更新,之前转载的博客虽然胜在详细,但 ...

  10. 最近公共祖先算法LCA笔记(树上倍增法)

    Update: 2019.7.15更新 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了. 万分感谢[宁信]大佬,认认真真地审核了本文章,指出了超过五处错误捂脸,太尴尬了 ...

随机推荐

  1. Yii2 查询条件

    Model::find() 字符串格式,例如:'status=1' 哈希格式,例如: ['status' => 1, 'type' => 2] 操作符格式,例如:['like', 'nam ...

  2. 【PHP开发规范】继承与扩展:PSR-2 编码风格规范

    之前的一篇文章是对PSR-1的基本介绍 接下来是PSR-2 编码风格规范,它是 PSR-1 基本代码规范的继承与扩展. PSR-1 和PSR-2是PHP开发中基本的编码规范,大家其实都可以参考学习下, ...

  3. uboot-2012.04.01移植编译前准备

    一:准备移植1.从下面的官网下载uboot-2012.04.012.建立sourceinsight工程 a.解压并在E:\colin weidongshan\transplant_u-boot-201 ...

  4. 大数据入门第二天——基础部分之zookeeper(上)

    一.概述 1.是什么? 根据凡技术必登其官网的原则,我们先去官网瞅一瞅:http://zookeeper.apache.org/ Apache ZooKeeper is an effort to de ...

  5. JavaWeb基础—JavaBean

    一.什么是JavaBean 一个遵循一定规范的普通的Java类 百度的JavaBean规范: (1)JavaBean 类必须是一个公共类,并将其访问属性设置为 public , 如: public c ...

  6. flex作图

    <?xml version="1.0" encoding="utf-8"?><s:Application xmlns:fx="htt ...

  7. 20155332 补交ch12课下作业

    20155332 补交ch12课下作业 课下测试提交晚了,我课后补做了一遍,答对13题,答错3题. 试题内容如下所示: 课本内容 1.并发(Concurrency) 访问慢I/O设备:就像当应用程序等 ...

  8. centos 中sshd莫名其妙不见了?

    发现问题 遇到问题:首先莫要慌:事出有因:先检查一波: 首先呢,看一下/var/log/yum.log  是否有误删的记录: 如有被误删的操作的话:可以去看看日志:到底咋回事: 然后么 yum ins ...

  9. 用html+css做机器猫 源代码

    先来看一下做出来的效果图,然后再来看源代码 是不是还是很像的 下面来看源代码 <!DOCTYPE html> <html lang="en"> <he ...

  10. scrapy的简单使用

    使用之前的创建虚拟环境方法(pipenv) 创建虚拟环境并进入虚拟环境 mkdir douban cd douban pipenv install pipenv shell 再安装我们的scrapy ...