1. DFS预处理出所有节点的深度和父节点
inline void dfs(int u)
{
int i;
for(i=head[u];i!=-;i=next[i])
{
if (!deep[to[i]])
{
deep[to[i]] = deep[u]+;
p[to[i]][] = u; //p[x][0]保存x的父节点为u;
dfs(to[i]);
}
}
}

2. 初始各个点的2^j祖先是谁 ,其中2^j(j=0...log(该点深度))倍祖先,1倍祖先就是父亲,2倍祖先是父亲的父亲......。

void init()
{
int i,j;
//p[i][j]表示i结点的第2^j祖先
for(j=;(<<j)<=n;j++)
for(i=;i<=n;i++)
if(p[i][j-]!=-)
p[i][j]=p[p[i][j-]][j-];//i的第2^j祖先就是i的第2^(j-1)祖先的第2^(j-1)祖先
}
3.从深度大的节点上升至深度小的节点同层,如果此时两节点相同直接返回此节点,即lca。
否则,利用倍增法找到最小深度的p[a][j]!=p[b][j],此时他们的父亲p[a][0]即lca。
int lca(int a,int b)//最近公共祖先
{
int i,j;
if(deep[a]<deep[b])swap(a,b);
for(i=;(<<i)<=deep[a];i++);
i--;
//使a,b两点的深度相同
for(j=i;j>=;j--)
if(deep[a]-(<<j)>=deep[b])
a=p[a][j];
if(a==b)return a;
//倍增法,每次向上进深度2^j,找到最近公共祖先的子结点
for(j=i;j>=;j--)
{
if(p[a][j]!=-&&p[a][j]!=p[b][j])
{
a=p[a][j];
b=p[b][j];
}
}
return p[a][];
}

LCA-倍增法(在线)O(nlogn)-O(logn)的更多相关文章

  1. POJ - 1330 Nearest Common Ancestors(dfs+ST在线算法|LCA倍增法)

    1.输入树中的节点数N,输入树中的N-1条边.最后输入2个点,输出它们的最近公共祖先. 2.裸的最近公共祖先. 3. dfs+ST在线算法: /* LCA(POJ 1330) 在线算法 DFS+ST ...

  2. LCA(最近公共祖先)——LCA倍增法

    一.前人种树 博客:最近公共祖先 LCA 倍增法 博客:浅谈倍增法求LCA 二.沙场练兵 题目:POJ 1330 Nearest Common Ancestors 代码: const int MAXN ...

  3. 最近公共祖先 LCA 倍增法

    [简介] 解决LCA问题的倍增法是一种基于倍增思想的在线算法. [原理] 原理和同样是使用倍增思想的RMQ-ST 算法类似,比较简单,想清楚后很容易实现. 对于每个节点u , ancestors[u] ...

  4. hdu2586 lca倍增法

    倍增法加了边的权值,bfs的时候顺便把每个点深度求出来即可 #include<iostream> #include<cstring> #include<cstdio> ...

  5. poj1470 LCA倍增法

    倍增法模板题 #include<iostream> #include<cstring> #include<cstdio> #include<queue> ...

  6. luogu3379 【模板】最近公共祖先(LCA) 倍增法

    题目大意:给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 整体步骤:1.使两个点深度相同:2.使两个点相同. 这两个步骤都可用倍增法进行优化.定义每个节点的Elder[i]为该节点的2^k( ...

  7. LCA—倍增法求解

    LCA(Least Common Ancestors) 即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 常见解法一般有三种 这里讲解一种在线算法-倍增 首先我们定义fa[u][j ...

  8. LCA - 倍增法去求第几个节点

    You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, ...

  9. POJ 1330(LCA/倍增法模板)

    链接:http://poj.org/problem?id=1330 题意:q次询问求两个点u,v的LCA 思路:LCA模板题,首先找一下树的根,然后dfs预处理求LCA(u,v) AC代码: #inc ...

  10. 【模板】Lca倍增法

    Codevs 1036 商务旅行 #include<cstdio> #include<cmath> #include<algorithm> using namesp ...

随机推荐

  1. 组合,关联,聚合的区别(转自http://jimmyleeee.blog.163.com/blog/static/9309618200932014422932/)

    类间关系 在类图中,除了需要描述单独的类的名称.属性和操作外,我们还需要描述类之间的联系,因为没有类是单独存在的,它们通常需要和别的类协作,创造比单独工作更大的语义.在UML类图中,关系用类框之间的连 ...

  2. [妙味JS基础]第十课:日期对象、时钟倒计时

    知识点总结 时间.年.月.日.时.分.秒 new Date() ->当前系统的时间对象 数字类型: getFullYear().getYear().getUTCFullYear() getYea ...

  3. bootstrap复习:组件

    一.下拉菜单 1.实例:将下拉菜单触发器和下拉菜单都包裹在 .dropdown 里,或者另一个声明了 position: relative; 的元素.然后加入组成菜单的 HTML 代码.为下拉菜单的父 ...

  4. NSCondition

    一.NSCondition是对条件变量和互斥量的一个封装,用于线程之间的同步. 其中的互斥量用于保护对条件变量的修改,条件变量变化以信号量的方式通知其它线程实现线程之间的同步. 二.NSConditi ...

  5. Objetive-C 中的相等比较

    1.== 用于比较两个对象的地址是否相同 1)需要注意的是相同的短字符串,一定大小整数(nsnumber),Objetive-C 底层会做cache,两个对象,指向同一个地址. 例如: NSStrin ...

  6. Worker+MQ解惑

    用Worker来保证数据的一致性,再加上MQ来便于水平扩展,也提升了Worker的效率.这就是传说中的Worker+MQ,又叫做可靠消息方式.另外,将任务的查询和执行分工,形成父子任务,达到真正的分布 ...

  7. Gentoo/Funtoo USE标记介绍

    Gentoo/Funtoo USE标记 USE的简单理解如下:一个软件不只包含软件本身,还包括其组件,如,文档,插件,GUI支持等.USE就是用来标记是否要安装软件的同时安装这些组件. 声明USE标记 ...

  8. OC之KVC,KVO

    KVO简介 在 Cocoa 的模型-视图-控制器 (Model-view-controller)架构里,控制器负责让视图和模型同步.这一共有两步:当 model 对象改变的时候,视图应该随之改变以反映 ...

  9. spring实现读写分离

    (转自:http://www.cnblogs.com/surge/p/3582248.html) 现在大型的电子商务系统,在数据库层面大都采用读写分离技术,就是一个Master数据库,多个Slave数 ...

  10. javascript焦点图(根据图片下方的小框自动播放)

    html和css就不详细说明了,也是简单布局,通过定位把跟随图片的小框,定位到图片下方 <!DOCTYPE html> <html> <head> <meta ...