概述

对于有根树T的两个结点u、v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u、v的祖先且x的深度尽可能大。

如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4

在本篇中我们先介绍一下倍增算法

我们需要一个数组de[i]来表示每一个节点i的深度,用另一数组parent[i][j]来表示每一节点j向上走2的i次方是哪个节点

我们首先在初始化中算出每个点的深度和它的上一个点是什么(用parent[0][i]表示)

在此后我们进行倍增的处理:parent[1][j]=parent[0][parent[0][j]]......parent[i+1][j]=parent[i][parent[i][j]]

当然如果已经走到根节点了,就将其它的parent全设为0

然后我们就可以搞lca了:给你两个点想x,y,让y成为深的那个,如果x,y深度不等就让y倍增地往上跳。

当x,y深度相等时凡是它俩不相等就倍增地跳,最后它们中任意一个的父节点及他们的最近公共祖先

模板

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int LOG=18;
vector<int>g[500010];
int de[500010];
int parent[LOG+3][500010];
void dfs(int now,int dep,int be)
{     parent[0][now]=be;
      de[now]=dep;
      for(int i=0;i<g[now].size();i++)
         if(g[now][i]!=be)
           dfs(g[now][i],dep+1,now);
}
int lca(int x,int y)
{     if(de[x]>de[y])swap(x,y);
         for(int i=LOG;i>=0;i--)
            if(de[parent[i][y]]>=de[x]&&parent[i][y]>0)
              y=parent[i][y];
      if(x==y)return x;
      for(int i=LOG;i>=0;i--)
         if(parent[i][x]!=parent[i][y])
           x=parent[i][x],y=parent[i][y];
      return parent[0][x];
}
int main()
{     int n,m,s,i,j,k,p,q;
      scanf("%d%d%d",&n,&m,&s);
      for(i=1;i<n;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          g[x].push_back(y);
          g[y].push_back(x);
      }
      dfs(s,0,0);
      for(i=0;i<LOG;i++)
         for(j=1;j<=n;j++)
            if(parent[i][j]<=0)parent[i+1][j]=-1;
              else parent[i+1][j]=parent[i][parent[i][j]];
      for(i=1;i<=m;i++){
          int x,y;
          scanf("%d%d",&x,&y);
          printf("%d\n",lca(x,y));
      }
      return 0;
}

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

  1. LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现

    首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...

  2. POJ 1330 LCA最近公共祖先 离线tarjan算法

    题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...

  3. caioj 1236 最近公共祖先 树倍增算法模版 倍增

    [题目链接:http://caioj.cn/problem.php?id=1236][40eebe4d] 代码:(时间复杂度:nlogn) #include <iostream> #inc ...

  4. LCA最近公共祖先 Tarjan离线算法

    学习博客:  http://noalgo.info/476.html 讲的很清楚! 对于一颗树,dfs遍历时,先向下遍历,并且用并查集维护当前节点和父节点的集合.这样如果关于当前节点(A)的关联节点( ...

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

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

  6. P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)

    为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...

  7. LCA 近期公共祖先 小结

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

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

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

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

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

  10. LCA近期公共祖先

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

随机推荐

  1. 第一个程序python.py

    print("hello word")print("hello hello")print("hello hello")print(" ...

  2. python的while循环

    age_of_laochuanzhang = 56 conut = 0 while True: if conut == 3: print("输入次数上限") break age = ...

  3. Shell脚本之反引号【``】和 $()

    一.奇怪的返回 今天在搞监控的时候,修改一个老脚本,主要是通过对操作系统进行判断来获取不同的监控参数.(获取top参数在不同操作系统上也有个坑,会在另外一篇里面写) 脚本如下,非常简单: #处理Cen ...

  4. C#要点补充

    1字符串与时间的互转 DateTime.TryParse将空字符串.为null或格式不正确,则转换为的DateTime所代表的值为:0001/1/1 0:00:00,此为DateTime.MinVal ...

  5. mxnet框架样本,使用C++接口

    哇塞,好久么有跟进mxnet啦,python改版了好多好多啊,突然发现C++用起来才是最爽的. 贴一个mxnet中的C++Example中的mlp网络和实现,感觉和python对接毫无违和感.真是一级 ...

  6. NPOI操作Excel 踩坑记

    1 读取Excel并修改单元格 a.一定不能一边读数据,一边修改单元格,否则读出来的数据可能不准 b.注意写文件的模式,不然修改后的文件,打开会报错. c.清空单元格的数据,可以调用SetCellTy ...

  7. NOI 2004 郁闷的出纳员

    Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常 ...

  8. python写一个DDos脚本(DOS)

    前言:突然想写,然后去了解原理 DDOS原理:往指定的IP发送数据包(僵尸网络),导致服务器 拒绝服务,无法正常访问. 0x01: 要用到的模块 scapy模块 pip install scapy 或 ...

  9. JXLS 2.4.0系列教程(三)——嵌套循环是怎么做到的

    注:本文代码在第一篇文章基础上修改而成,请务必先阅读第一篇文章. http://www.cnblogs.com/foxlee1024/p/7616987.html 本文也不会过多的讲解模板中遍历表达式 ...

  10. 安装Ubuntu16.04失败

    原本安装的是Ubuntu14,但是在使用caffe时总是出错,所以干脆将Ubuntu从14升级到16,结果整出一堆麻烦.在解决这些麻烦的过程也学习了不少系统启动的细节.印证了那句话"如何没有 ...