LCA(最近公共祖先)——离线 Tarjan 算法
tarjan算法的步骤是(当dfs到节点u时):
1 在并查集中建立仅有u的集合,设置该集合的祖先为u
1 对u的每个孩子v:
1.1 tarjan之
1.2 合并v到父节点u的集合,确保集合的祖先是u
2 设置u为已遍历
3 处理关于u的查询,若查询(u,v)中的v已遍历过,则LCA(u,v)=v所在的集合的祖先
不懂请点击
伪代码:
Tarjan(u)//marge和find为并查集合并函数和查找函数
{
for each(u,v) //访问所有u子节点v
{
Tarjan(v); //继续往下遍历
marge(u,v); //合并v到u上
标记v被访问过;
}
for each(u,e) //访问所有和u有询问关系的e
{
如果e被访问过;
u,e的最近公共祖先为find(e);
}
}
模板:
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = ; int rank[maxn]; //并查集结点高度
int pre[maxn]; //并查集父节点
int anc[maxn]; //祖先
int indgree[maxn]; //保存每个节点的入度
bool vis[maxn];
vector<int> tree[maxn]; //保存树
vector<int> qes[maxn]; //保存查询
int vertex_num; //顶点数 void init()
{
memset(rank,,sizeof(rank));
memset(vis,,sizeof(vis));
memset(indgree,,sizeof(indgree));
memset(anc,,sizeof(anc));
for(int i=;i<=vertex_num;i++){
pre[i] = i;
tree[i].clear();
qes[i].clear();
}
} int find_pre(int x) //查找函数
{
if(pre[x] == x){
return x;
}
else{
pre[x] = find_pre(pre[x]); //压缩路径
}
return pre[x];
} void Union(int x,int y)
{
x = find_pre(x);
y = find_pre(y);
if(x == y){
return ;
}
else{
if(rank[x] > rank[y]){
pre[y] = x;
}
else if(rank[x] == rank[y]){ //x和y深度相同时, y向x合并
rank[x]++;
pre[y] = x;
}
else{
pre[x] = y;
}
}
} int lca(int u)
{
anc[u] = u;
for(int i=;i<tree[u].size();i++){
lca(tree[u][i]);
Union(u,tree[u][i]);
anc[find_pre(u)]=u;
}
vis[u] = ;
for(int i=;i<qes[u].size();i++){
if(vis[qes[u][i]] == ){
return anc[find_pre(qes[u][i])];
}
}
} int main()
{
cout<<"请输入顶点数:";
cin>>vertex_num;
init();
int u,v,ans;
cout<<"请依次输入各边:\n";
for(int i=;i<vertex_num;i++){
cin>>u>>v;
tree[u].push_back(v);
indgree[v]++;
}
cout<<"请输入要查询的两个数:";
cin>>u>>v;
qes[u].push_back(v);
qes[v].push_back(u);
for(int i=;i<=vertex_num;i++){
if(indgree[i] == ){
ans = lca(i);
printf("(%d,%d)的LCA是:%d\n",u,v,ans);
break;
}
}
return ;
}
上一个图,来测试模板:

题目:POJ 1470
代码:点击
/*
* POJ 1470
* 给出一颗有向树,Q个查询
* 输出查询结果中每个点出现次数
*/
/*
* LCA离线算法,Tarjan
* 复杂度O(n+Q);
*/
LCA(最近公共祖先)——离线 Tarjan 算法的更多相关文章
- POJ 1330 LCA最近公共祖先 离线tarjan算法
题意要求一棵树上,两个点的最近公共祖先 即LCA 现学了一下LCA-Tarjan算法,还挺好理解的,这是个离线的算法,先把询问存贮起来,在一遍dfs过程中,找到了对应的询问点,即可输出 原理用了并查集 ...
- 图论-最近公共祖先-离线Tarjan算法
有关概念: 最近公共祖先(LCA,Lowest Common Ancestors):对于有根树T的两个结点u.v,最近公共祖先表示u和v的深度最大的共同祖先. Tarjan是求LCA的离线算法(先存储 ...
- P5836 [USACO19DEC]Milk Visits S 从并查集到LCA(最近公共祖先) Tarjan算法 (初级)
为什么以它为例,因为这个最水,LCA唯一黄题. 首先做两道并查集的练习(估计已经忘光了).简单来说并查集就是认爸爸找爸爸的算法.先根据线索理认爸爸,然后查询阶段如果发现他们的爸爸相同,那就是联通一家的 ...
- LCA最近公共祖先(Tarjan离线算法)
这篇博客对Tarjan算法的原理和过程模拟的很详细. 转载大佬的博客https://www.cnblogs.com/JVxie/p/4854719.html 第二次更新,之前转载的博客虽然胜在详细,但 ...
- POJ1330Nearest Common Ancestors——近期公共祖先(离线Tarjan)
http://poj.org/problem? id=1330 给一个有根树,一个查询节点(u,v)的近期公共祖先 836K 16MS #include<iostream> #includ ...
- [HDOJ2586]How far away?(最近公共祖先, 离线tarjan, 并查集)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 这题以前做过…现在用tarjan搞一发…竟然比以前暴力过的慢………… 由于是离线算法,需要Que ...
- POJ 1986 Distance Queries (最近公共祖先,tarjan)
本题目输入格式同1984,这里的数据范围坑死我了!!!1984上的题目说边数m的范围40000,因为双向边,我开了80000+的大小,却RE.后来果断尝试下开了400000的大小,AC.题意:给出n个 ...
- 近期公共祖先(LCA)——离线Tarjan算法+并查集优化
一. 离线Tarjan算法 LCA问题(lowest common ancestors):在一个有根树T中.两个节点和 e&sig=3136f1d5fcf75709d9ac882bd8cfe0 ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载)
Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)(转载) 转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2 ...
- LCA最近公共祖先——Tarjan模板
LCA(Lowest Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. Tarjan是一种离线算法,时间复杂度O(n+Q),Q表示询问次数,其中 ...
随机推荐
- js中实现页面跳转(返回前一页、后一页)
一:JS 重载页面,本地刷新,返回上一页 代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a ...
- 分布式压测系列之Jmeter4.0第一季
1)Jmeter4.0介绍 jmeter是个纯java编写的开源压测工具,apache旗下的开源软件,一开始是设计为web测试的软件,由于发展迅猛,现在可以压测许多协议比如:http.https.so ...
- 技巧:Vimdiff 使用
技巧:Vimdiff 使用 各种 IDE 大行其道的同时,传统的命令行工具以其短小精悍,随手可得的特点仍有很大的生存空间,这篇短文介绍了一个文本比较和合并的小工具:vimdiff.希望能对在 Unix ...
- Java程序如何生成Jar 执行文件(2)
一.用Eclipse生产Jar文件 注意:此方法可以打包含有第三方jar包的项目 1. 首先,右键你的Java工程,选择Export,在Java文件夹下选择Runnable JAR file,如下图所 ...
- PHP | Uploading and reading of files and database 【PHP | 文件的上传和读取与数据库】
这是我自己的一个作业,用的是很基础的代码. 有错误的地方欢迎批评和指正! 这里最容易出错的地方在读取数据后向数据库表中插入数据是的数据格式! 文件上传的页面 uploading.php <htm ...
- CentOS7.2中安装MongoDB
MongoDB是由C++编写的NoSQL的分布式文件数据库,用的json格式的k-value存储方式. MongoDB官网 https://www.mongodb.com 一.下载和安装 下载完后文件 ...
- 【linux运维递进】
================================云计算和虚拟化=================================== docker openstack svn git ...
- elasticsearch 5.x 系列之六 文档索引,更新,查询,删除流程
一.elasticsearch index 索引流程 步骤: 客户端向Node1 发送索引文档请求 Node1 根据文档ID(_id字段)计算出该文档应该属于shard0,然后请求路由到Node3的P ...
- springboot学习(2)
WebMvcConfigurerAdapter 在springboot2.0及以上版本过时问题 WebMvcConfigurerAdapter已经过时,替代方案: 1 实现 WebMvcConfigu ...
- NAND Flash结构及驱动函数
目标:以NAND Flash K9F2G08U0M为例介绍其结构及其驱动程序的书写 1. 结构 由芯片手册中的图可知:K9F2G08U0M大小为2112Mbits(即 256MB = 2Gb ) 共有 ...