tarjan求lca的神奇
题目描述
如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。
输入输出格式
输入格式:
第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。
接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。
接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。
输出格式:
输出包含M行,每行包含一个正整数,依次为每一个询问的结果。
输入输出样例
5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
4
4
1
4
4
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=10
对于70%的数据:N<=10000,M<=10000
对于100%的数据:N<=500000,M<=500000
~~~~~~~~~~~~~~~华丽的分割线~~~~~~~~~~~~~~~
对于此题,常规解法就是暴力。
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
炸死你。
倍增,可以有效降低复杂度,我也是学了两次之后掌握了它。
这里,我想记录下不久前学习的tarjan求lca
(tarjan真是好东西)
说它是tarjan,其实给我的感觉就是套了一个tarjan的名字罢了。(类似我的dijksPA)其实它就是一个dfs的神奇过程。
先放代码再说
#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int n,m,p;
struct edge
{
int next,to,lca;
}e[maxn<<],e1[maxn<<];
int head[maxn<<],cnt,head1[maxn<<];
inline int addedge(int from,int to)//前向星存图
{
e[++cnt].next=head[from];
e[cnt].to=to;
head[from]=cnt;
}
inline int add (int from,int to)//前向星存储查询
{
e1[++cnt].next=head1[from];
e1[cnt].to=to;
head1[from]=cnt;
}
int f[maxn<<],vis[maxn<<];
int find(int x)//并查集找爹函数
{
if(f[x]!=x)
f[x]=find(f[x]);
return f[x];
}
int tarjan(int u)//神奇的dfs
{
f[u]=u;//爸爸
vis[u]=;//走过
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(!vis[v])
{
tarjan(v);
f[v]=u;//爹
}
}
for(int i=head1[u];i;i=e1[i].next)//询问的图
{
int v=e1[i].to;
if(vis[v])
{
e1[i].lca=find(v);
if(i%==)
e1[i+].lca=e1[i].lca;//
else
e1[i-].lca=e1[i].lca;
}
}
} int main()
{
scanf("%d%d%d",&n,&m,&p);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
for(int i=;i<=n;i++)
f[i]=i;//初始化并查集
cnt=;//因为上面村边用过cnt,所以把它拍成0
for(int i=;i<=m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
tarjan(p);//从根节点开始dfs
for(int i=;i<=m;i++)
{
printf("%d\n",e1[i*].lca);
}
return ;
}
1.任选一个点为根节点,从根节点开始。
2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
3.若是v还有子节点,返回2,否则下一步。
4.合并v到u上。
5.寻找与当前点u有询问关系的点v。
6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
https://www.cnblogs.com/JVxie/p/4854719.html这位大佬的模拟过程真的很强
总的来说,感觉这个算法不是太常用吧。大数据的情况下可能没有倍增快,码量也没小到那里去,而且到现在我还是懵懵的。
写个博客记录一下吧。
tarjan求lca的神奇的更多相关文章
- 【Tarjan】洛谷P3379 Tarjan求LCA
题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...
- 倍增\ tarjan求lca
对于每个节点v,记录anc[v][k],表示从它向上走2k步后到达的节点(如果越过了根节点,那么anc[v][k]就是根节点). dfs函数对树进行的dfs,先求出anc[v][0],再利用anc[v ...
- Tarjan求LCA
LCA问题算是一类比较经典的树上的问题 做法比较多样 比如说暴力啊,倍增啊等等 今天在这里给大家讲一下tarjan算法! tarjan求LCA是一种稳定高速的算法 时间复杂度能做到预处理O(n + m ...
- 详解使用 Tarjan 求 LCA 问题(图解)
LCA问题有多种求法,例如倍增,Tarjan. 本篇博文讲解如何使用Tarjan求LCA. 如果你还不知道什么是LCA,没关系,本文会详细解释. 在本文中,因为我懒为方便理解,使用二叉树进行示范. L ...
- 倍增 Tarjan 求LCA
...
- SPOJ 3978 Distance Query(tarjan求LCA)
The traffic network in a country consists of N cities (labeled with integers from 1 to N) and N-1 ro ...
- Tarjan求LCA(离线)
基本思想 把要求的点对保存下来,在dfs时顺带求出来. 方法 将每个已经遍历的点指向它回溯的最高节点(遍历它的子树时指向自己),每遍历到一个点就处理它存在的询问如果另一个点已经遍历,则lca就是另一个 ...
- 图论分支-倍增Tarjan求LCA
LCA,最近公共祖先,这是树上最常用的算法之一,因为它可以求距离,也可以求路径等等 LCA有两种写法,一种是倍增思想,另一种是Tarjan求法,我们可以通过一道题来看一看, 题目描述 欢乐岛上有个非常 ...
- Tarjan求LCA总结
Tarjan算法向上标记法:从x向上走到根节点,并标记所有经过的点从y向上走到根节点,当第一次遇到已标记的节点时,就找到了LCA(x, y)对于每个询问,向上标记法的时间复杂度最坏为O(n) 在深度遍 ...
随机推荐
- 【CV现状-3.3】特征提取与描述
#磨染的初心--计算机视觉的现状 [这一系列文章是关于计算机视觉的反思,希望能引起一些人的共鸣.可以随意传播,随意喷.所涉及的内容过多,将按如下内容划分章节.已经完成的会逐渐加上链接.] 缘起 三维感 ...
- springmvc处理局部异常和全局异常
springmvc通过HandlerExceptionResolver(是一个接口,在spring-webmvc依赖下)处理程序异常,包括处理器异常.数据绑定异常以及处理器执行时发生的异常.Handl ...
- Flex 布局——语法属性详解
前言 Flexbox 是 flexible box 的简称(注:意思是“灵活的盒子容器”),是 CSS3 引入的新的布局模式.它决定了元素如何在页面上排列,使它们能在不同的屏幕尺寸和设备下可预测地展现 ...
- cocos2d-x 系统学习cocos(2) 交互
交互 玩游戏的时候,我们需要用输入设备和游戏进行交互,那么游戏需要对玩家做出相应,比如说按下键盘的上下左右,角色就朝着对应的方向移动,按下技能键,角色就释放技能 键盘监听 响应 cocos2d-x中要 ...
- C# 动态(不定)类型和不定参数数量,使用param写入CSV文档的最简单方法,提供excel(或记事本)阅读支持格式
在开发一个项目,使用C#写入CSV文件时,虽并未遇到太多阻碍,但是很多小伙伴估计和我有过同样的想法.简单的写入CSV,固定参数数量就好了很简单写完.但是如果遇到你得到的数据参数数量和参数类型未知或者动 ...
- Hydra爆破神器使用
参数详解: -R 根据上一次进度继续破解-S 使用SSL协议连接-s 指定端口-l 指定用户名-L 指定用户名字典(文件)-p 指定密码破解-P 指定密码字典(文件)-e 空密码探测和指定用户密码探测 ...
- 存储物理页属性的PFN数据库
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 存储物理页属性的PFN数据库 一.PFN的基础概念 页帧:即CPU ...
- linux::jsoncpp库
下载库:http://sourceforge.net/projects/jsoncpp/files/ tar -zxvf jsoncpp-src- -C jsoncpp () 安装 scons $ s ...
- 04 Node.js学习笔记之模块的加载
A文件代码: //1.require是一个方法,它的作用就是用来加载模块的 console.log("执行 B ") require('./b.js'); console.log( ...
- openflow流表项中有关ip掩码的匹配的问题(控制器为ryu)
一.写在前面 唉,被分配到sdn安全方向,顶不住,顶不住,感觉搞不出来什么有搞头的东西.可若是让我水水的应付,我想我也是做不到的,世上无难事只怕有心人.好了,进入正题,本次要讨论的时一个比较细节的东西 ...