题目描述

如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

输入输出格式

输入格式:

第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

输出格式:

输出包含M行,每行包含一个正整数,依次为每一个询问的结果。

输入输出样例

输入样例#1:

5 5 4
3 1
2 4
5 1
1 4
2 4
3 2
3 5
1 2
4 5
输出样例#1:

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的神奇的更多相关文章

  1. 【Tarjan】洛谷P3379 Tarjan求LCA

    题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每 ...

  2. 倍增\ tarjan求lca

    对于每个节点v,记录anc[v][k],表示从它向上走2k步后到达的节点(如果越过了根节点,那么anc[v][k]就是根节点). dfs函数对树进行的dfs,先求出anc[v][0],再利用anc[v ...

  3. Tarjan求LCA

    LCA问题算是一类比较经典的树上的问题 做法比较多样 比如说暴力啊,倍增啊等等 今天在这里给大家讲一下tarjan算法! tarjan求LCA是一种稳定高速的算法 时间复杂度能做到预处理O(n + m ...

  4. 详解使用 Tarjan 求 LCA 问题(图解)

    LCA问题有多种求法,例如倍增,Tarjan. 本篇博文讲解如何使用Tarjan求LCA. 如果你还不知道什么是LCA,没关系,本文会详细解释. 在本文中,因为我懒为方便理解,使用二叉树进行示范. L ...

  5. 倍增 Tarjan 求LCA

                                                                                                         ...

  6. 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 ...

  7. Tarjan求LCA(离线)

    基本思想 把要求的点对保存下来,在dfs时顺带求出来. 方法 将每个已经遍历的点指向它回溯的最高节点(遍历它的子树时指向自己),每遍历到一个点就处理它存在的询问如果另一个点已经遍历,则lca就是另一个 ...

  8. 图论分支-倍增Tarjan求LCA

    LCA,最近公共祖先,这是树上最常用的算法之一,因为它可以求距离,也可以求路径等等 LCA有两种写法,一种是倍增思想,另一种是Tarjan求法,我们可以通过一道题来看一看, 题目描述 欢乐岛上有个非常 ...

  9. Tarjan求LCA总结

    Tarjan算法向上标记法:从x向上走到根节点,并标记所有经过的点从y向上走到根节点,当第一次遇到已标记的节点时,就找到了LCA(x, y)对于每个询问,向上标记法的时间复杂度最坏为O(n) 在深度遍 ...

随机推荐

  1. Linux内存描述之内存页面page–Linux内存管理(四)

    服务器体系与共享存储器架构 日期 内核版本 架构 作者 GitHub CSDN 2016-06-14 Linux-4.7 X86 & arm gatieme LinuxDeviceDriver ...

  2. SQL SERVER数据库,按年、月、日、时、分、秒计算两个时间字段之间的间隔时间样例

    使用DATEDIFF(取值,时间字段1,时间字段2) 举例: SELECT DATEDIFF(YEAR,DRYSJ,DCYSJ),* FROM YXHIS2019..TBZYBR2019 --SQL ...

  3. 开发 Django 博客文章阅读量统计功能

    作者:HelloGitHub-追梦人物 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库 如何精确地记录一篇文章的阅读量是一个比较复杂的问题,不过对于我们的博客来说,没有必要 ...

  4. 【Java必修课】一图说尽排序,一文细说Sorting(Array、List、Stream的排序)

    简说排序 排序是极其常见的使用场景,因为在生活中就有很多这样的实例.国家GDP排名.奥运奖牌排名.明星粉丝排名等,各大排行榜,给人的既是动力,也是压力. 而讲到排序,就会有各种排序算法和相关实现,本文 ...

  5. Vue的介绍及安装和导入

    08.27自我总结 Vue的介绍及安装和导入 本质就是封装一些js 一Vue的介绍 进式 JavaScript 框架 通过对框架的了解与运用程度,来决定其在整个项目中的应用范围,最终可以独立以框架方式 ...

  6. Travis CI持续集成使用

    用好这个工具不仅可以提高效率,还能使开发流程更可靠和专业化,从而提高软件的价值.而且,它对于开源项目是免费的,不花一分钱,就能帮你做掉很多事情. 一.什么是持续集成? Travis CI 提供的是持续 ...

  7. 介绍ArcGIS中各种数据的打开方法——shp(矢量文件)

    2.加载shp文件到地图控件 ShapeFile是一种矢量数据模型的计算机数据组织文件,用于在计算机上表达矢量数据的计算机文件. 加载ShapeFile文件最主要是:axMapControll控件对象 ...

  8. Oracle注入之带外通信

    Oracle注入之带外通信和DNSLOG注入非常相似,例如和mysql中load_file()函数实现无回显注入非常相似. 下面介绍这个技术中常用的函数和使用. 环境这里准备两台测试,一台注入点的靶机 ...

  9. Centos 7 集成安装Apache+PHP+Kerberos+LDAP+phpLDAPadmin

    一.安装Apache 1.1.安装Apache Apache程序是目前拥有很高市场占有率的Web服务程序之一,其跨平台和安全性广泛被认可且拥有快速.可靠.简单的API扩展. 它的名字取自美国印第安人土 ...

  10. 数据结构1_java---单链表的操作,约瑟夫问题

    我们经常实用c++来建立链表,为了学习的方便,此处我使用java实现了对链表的增删改查功能 整个过程较为简单.仅供参考 流程: (1)通过内部类Node建立结点,内部变量作为指针域和数据域,并写下构造 ...