LCA(最近公共祖先)之倍增算法
概述
对于有根树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(最近公共祖先)之倍增算法的更多相关文章
- LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现
首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵 ...
- POJ 1330 LCA最近公共祖先 离线tarjan算法
题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...
- caioj 1236 最近公共祖先 树倍增算法模版 倍增
[题目链接:http://caioj.cn/problem.php?id=1236][40eebe4d] 代码:(时间复杂度:nlogn) #include <iostream> #inc ...
- LCA最近公共祖先 Tarjan离线算法
学习博客: http://noalgo.info/476.html 讲的很清楚! 对于一颗树,dfs遍历时,先向下遍历,并且用并查集维护当前节点和父节点的集合.这样如果关于当前节点(A)的关联节点( ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)
为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...
- LCA 近期公共祖先 小结
LCA 近期公共祖先 小结 以poj 1330为例.对LCA的3种经常使用的算法进行介绍,分别为 1. 离线tarjan 2. 基于倍增法的LCA 3. 基于RMQ的LCA 1. 离线tarjan / ...
- LCA(最近公共祖先)模板
Tarjan版本 /* gyt Live up to every day */ #pragma comment(linker,"/STACK:1024000000,1024000000&qu ...
- CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )
CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...
- LCA近期公共祖先
LCA近期公共祖先 该分析转之:http://kmplayer.iteye.com/blog/604518 1,并查集+dfs 对整个树进行深度优先遍历.并在遍历的过程中不断地把一些眼下可能查询到的而 ...
随机推荐
- python的while循环
age_of_laochuanzhang = 56 conut = 0 while True: if conut == 3: print("输入次数上限") break age = ...
- 献给迷惘的Java架构工程师
1. 工程化专题 (团队大于3个人之后,你需要去考虑团队合作,科学管理) 2. 源码分析专题 (好的程序员,一行代码一个设计就能看出来,源码分析带你品味代码,感受架构) 3.高性能及分布式专题 ( ...
- 我的第一次Pascal程序
今天刚刚来学点Pascal语言,都怪我买的书大多是用Pascal语言写的,所以我只能试着学一点咯! 来一段程序员最经典的Hello World! ; begin write('Hello World! ...
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- js实现深拷贝和浅拷贝
浅拷贝: 思路----------把父对象的属性,全部拷贝给子对象,实现继承. 问题---------如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,不会开辟新栈,不是 ...
- 【LeetCode】476. Number Complement (java实现)
原题链接 https://leetcode.com/problems/number-complement/ 原题 Given a positive integer, output its comple ...
- oracle创建函数和调用存储过程和调用函数的例子(区别)
创建函数: 格式:create or replace function func(参数 参数类型) Return number Is Begin --------业务逻辑--------- End; ...
- 浅谈localStorage、sessionStorage 与cookie
由于工作的需要,今天使用了下localStorage.sessionStorage和cookie,感觉这玩意儿还挺好用的. 关于localStorage与sessionStorage的知识点以及用法之 ...
- POJ 3790 最短路径问题(Dijkstra变形——最短路径双重最小权值)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3790 Problem Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你 ...
- 读懂_countof,可以懂得什么
在c++开发中数组是我们经常使用存储结构,而于此同时"数组越界"是每个c++程序员不能不提防陷阱. 还好,我们有预定义宏_countof. 一.在visual c++开发环境下,它 ...