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表示询问次数,其中 ...
随机推荐
- SpringBoot非官方教程 | 第六篇:springboot整合mybatis
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot-mybatis/ 本文出自方志朋的博客 本文主要 ...
- iOS Alamofire插件使用方法
let parameters = [ " ] Alamofire.request("http://110.185.104.100:8888/skproject/HvLogistic ...
- TCP三次挥手四次握手
三次握手: 客户端发起: 1.向服务器端发送报文SYN=1,ACK=0;客户端进入SYN-SEND状态. 2.服务端收到SYN=1,ACK=0的请求报文,向客户端返回确认报文SYN=1,ACK=1,服 ...
- 一个简易的android浏览器。求指教!
开发android的浏览器很简单吧,不过这浏览器倒是很简易.下面每一处代码都备注上注解了!废话不多说,下面直接上代码! 运行后界面 主界面的代码 activity_main.xml布局 <L ...
- js onsubmit和return false的关系
一直以来,我都是以为onsubmit=“return false”就不会进行提交,但经过项目之后才知道return false只是避免了之后的跳转,但onsubmit已经是正在进行了,故onsubmi ...
- Python全栈day 02
Python全栈day 02 一.循环语句 while 用法 num = 1 while num <= 10: print(num) num += 1 # 循环打印输出1-10 while el ...
- Apache Struts最新漏洞 远程代码执行漏洞预警 2018年11月08日
2018年11月8日,SINE安全监控检测中心,检测到Apache Struts官方更新了一个Struts漏洞补丁,这个漏洞是Apache Struts目前最新的漏洞,影响范围较广,低于Apache ...
- 嵌入式框架Zorb Framework搭建四:状态机的实现
我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮. 嵌入式框架Zorb Framework搭建过程 嵌入式框架Zorb Framework搭建一:嵌入式环境搭建.调试输出和建立时间系 ...
- UVa Problem 100 The 3n+1 problem (3n+1 问题)
参考:https://blog.csdn.net/metaphysis/article/details/6431937 #include <iostream> #include <c ...
- CERC2017 Gambling Guide,最短路变形,期望dp
题意 给定一个无向图,你需要从1点出发到达n点,你在每一点的时候,使用1个单位的代价,随机得到相邻点的票,但是你可以选择留在原地,也可以选择使用掉这张票,问到达n点的最小代价的方案的期望是多少. 分析 ...