luogu3379 【模板】最近公共祖先(LCA) Tarjan
LCA的Tarjan算法是一个离线算法,复杂度$O(n+q)$。
我们知道Dfs搜索树时会形成一个搜索栈。搜索栈顶节点cur时,对于另外一个节点v,它们的LCA便是v到根节点的路径与搜索栈开始分叉的那个节点lca。而站在cur上枚举v找lca的过程可以用并查集优化到$O(\log n)$级别。
并查集的定义:规定v为已经搜索且已经回溯,当前搜索栈顶为cur,则v并查集中的Father为LCA(cur,v)。查询可直接运用该定义。
并查集的维护:每当搜索栈顶弹出一个节点x时,将x在并查集中的Father设为其在树中的Father。这样x及x的子树的Father就都是这个栈内节点x->Father了。
注意,不要用vector,全部用邻接表,否则慢。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int MAX_NODE = 500010, MAX_PATH = 500010; struct Node;
struct Edge;
struct Path;
struct Link; struct Node
{
int DfsN;
Edge *Head;
Node *UnFa;//UnionFather
Node *Father;
Link *HeadLink;
}_nodes[MAX_NODE], *Root;
int TotNode; struct Edge
{
Node *To;
Edge *Next;
}_edges[MAX_NODE * 2];
int _eCount; struct Path
{
Node *From, *To;
Node *Lca;
}_paths[MAX_PATH];
int TotPath; struct Link
{
Node *To;
Path *Query;
Link *Next;
}_links[MAX_PATH * 2];
int LinkCnt; void AddEdge(Node *from, Node *to)
{
Edge *e = _edges + ++_eCount;
e->To = to;
e->Next = from->Head;
from->Head = e;
} void AddLink(Node *from, Node *to, Path *query)
{
Link *cur = _links + ++LinkCnt;
cur->To = to;
cur->Query = query;
cur->Next = from->HeadLink;
from->HeadLink = cur;
} void InitAllPath()
{
for (int i = 1; i <= TotPath; i++)
{
AddLink(_paths[i].From, _paths[i].To, _paths + i);
AddLink(_paths[i].To, _paths[i].From, _paths + i);
}
} Node *GetRoot(Node *cur)
{
return cur->UnFa == cur ? cur : cur->UnFa = GetRoot(cur->UnFa);
} void Tarjan(Node *cur, Node *fa)
{
cur->DfsN = 1;
cur->UnFa = cur;
cur->Father = fa;
for (Edge *e = cur->Head; e; e = e->Next)
{
if (e->To == cur->Father)
continue;
Tarjan(e->To, cur);
e->To->UnFa = cur;
}
for (Link *link = cur->HeadLink; link; link = link->Next)
if (link->To->DfsN == 2)
link->Query->Lca = GetRoot(link->To);
cur->DfsN = 2;
} int main()
{
int rootId;
scanf("%d%d%d", &TotNode, &TotPath, &rootId);
Root = _nodes + rootId;
for (int i = 1; i <= TotNode - 1; i++)
{
int u, v;
scanf("%d%d", &u, &v);
AddEdge(_nodes + u, _nodes + v);
AddEdge(_nodes + v, _nodes + u);
}
for (int i = 1; i <= TotPath; i++)
{
int u, v;
scanf("%d%d", &u, &v);
_paths[i].From = _nodes + u;
_paths[i].To = _nodes + v;
}
InitAllPath();
Tarjan(Root, NULL);
for (int i = 1; i <= TotPath; i++)
printf("%lld\n", _paths[i].Lca - _nodes);
return 0;
}
luogu3379 【模板】最近公共祖先(LCA) Tarjan的更多相关文章
- [模板] 最近公共祖先/lca
简介 最近公共祖先 \(lca(a,b)\) 指的是a到根的路径和b到n的路径的深度最大的公共点. 定理. 以 \(r\) 为根的树上的路径 \((a,b) = (r,a) + (r,b) - 2 * ...
- 最近公共祖先LCA(Tarjan算法)的思考和算法实现
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...
- 最近公共祖先 LCA Tarjan算法
来自:http://www.cnblogs.com/ylfdrib/archive/2010/11/03/1867901.html 对于一棵有根树,就会有父亲结点,祖先结点,当然最近公共祖先就是这两个 ...
- 最近公共祖先LCA Tarjan 离线算法
[简介] 解决LCA问题的Tarjan算法利用并查集在一次DFS(深度优先遍历)中完成所有询问.换句话说,要所有询问都读入后才开始计算,所以是一种离线的算法. [原理] 先来看这样一个性质:当两个节点 ...
- 最近公共祖先LCA(Tarjan算法)的思考和算法实现——转载自Vendetta Blogs
LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了f ...
- POJ 1986 Distance Queries (最近公共祖先,tarjan)
本题目输入格式同1984,这里的数据范围坑死我了!!!1984上的题目说边数m的范围40000,因为双向边,我开了80000+的大小,却RE.后来果断尝试下开了400000的大小,AC.题意:给出n个 ...
- Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)
Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...
- POJ 1470 Closest Common Ancestors(最近公共祖先 LCA)
POJ 1470 Closest Common Ancestors(最近公共祖先 LCA) Description Write a program that takes as input a root ...
- POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA)
POJ 1330 Nearest Common Ancestors / UVALive 2525 Nearest Common Ancestors (最近公共祖先LCA) Description A ...
- 【lhyaaa】最近公共祖先LCA——倍增!!!
高级的算法——倍增!!! 根据LCA的定义,我们可以知道假如有两个节点x和y,则LCA(x,y)是 x 到根的路 径与 y 到根的路径的交汇点,同时也是 x 和 y 之间所有路径中深度最小的节 点,所 ...
随机推荐
- Squid 正向代理
实现通过特定设备对特定的网址访问加速 使用squid 正向代理 实现,区别于反向代理,两者区别的根本在于作为中转的服务器在一个完整的请求中是代表客户端还是代表服务器. 服务端设置 1.安装程序包(推荐 ...
- RocketMQ学习笔记(13)----RocketMQ的Consumer消息重试
1. 概念 Producer端重试: 生产者端的消息失败,也就是Producer往MQ上发消息没有发送成功,比如网络抖动导致生产者发送消息到MQ失败. 这种消息失败重试我们可以手动设置发送失败重试的次 ...
- Xamarin绑定ios静态库
以下是官方的步骤介绍,我就不再一步步解释了 https://docs.microsoft.com/zh-cn/xamarin/ios/platform/binding-objective-c/walk ...
- 使用Way.EntityDB进行Entity Framework Core数据库建模
Way.EntityDB是一个基于EF Core的数据层框架,它取消了EF Core的Migration机制,因为Migration并不是通用的,比如说sql server生成的migration,如 ...
- CAD由一个自定义实体事件中的id得到自定义实体对象(com接口VB语言)
由一个自定义实体事件中的id得到自定义实体对象.该函数只能在自定义实体事件中调用. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 2 ...
- CAD得到ImageMark数据(com接口VB语言)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 3 ...
- EF-基础用法
一丶LINQ TO SQL 语法 基本格式: from c in 表名 where 条件 select c 二丶LINQ简介 LINQ是Language Integrated Query的简称,它是 ...
- KOA的简易模板引擎实现方式
上上一期链接--也就是本文的基础,参考KOA,5步手写一款粗糙的web框架 上一期链接--有关Router的实现思路,这份Koa的简易Router手敲指南请收下 本文参考仓库:点我 上一期科普了Rou ...
- Makefile,Shell command,Shell Language 之间的联系
1. Makefile 首先要知道Makefile 是什么东西,Makefile 是一个指令文件,里面存储着自定义的命令(可以借助已有的命令创造而来)在不同的系统下对Makefile 的区别不一样,L ...
- 爬虫-----HTML解析
对HTML的解析: 在解析复杂的HTML的页面时,需要避免一些问题,好让爬虫工作变得得心应手. • 寻找“打印此页”的链接,或者看看网站有没有HTML样式更友好的移动版(把自己 的请求头设置成处于移动 ...