这是LCA算法中的一种,Tarjan算法

其实这么说也有点不对,应该是Tarjan+DFS进行解决

LCA又称为最近公共祖先

那么什么是最近公共祖先:

在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点

而最近公共祖先,就是两个节点在这棵树上深度最大公共祖先节点

换句话说,最近公共祖先就是两个点在这棵树上距离最近的公共祖先节点

那么我们该如何去求这个最近公共祖先呢?

通常初学者都会想到最简单粗暴的一个办法:

对于每个询问,遍历所有的点,时间复杂度为O(n*q),很明显,n和q一般都是挺大的

常用的求LCA的算法有:

Tarjan/DFS+ST/倍增

后两个算法都是在线算法,也很相似,时间复杂度在O(logn)~O(nlogn)之间

有的题目是可以用线段树来做的,但是其代码量很大,

况且时间复杂度也挺高,在O(n)~O(nlogn)之间,但是优点在于简单粗暴

关于Tarjan算法:

1、  Tarjan算法是离线算法,需要预先读入所有的询问。

2、  Tarjan是基于并查集的。

3、  这个Tarjan算法跟求桥求连通块那个tarjan算法不一样(事实上tarjan发明过很多算法,貌似都叫tarjan算法)

4.任选一个点为根节点,从根节点开始。

5.遍历该点u所有子节点v,并标记这些子节点v已被访问过。

6.若是v还有子节点,返回2,否则下一步。

7.合并v到u上。

8.寻找与当前点u有询问关系的点v。

9.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。

遍历就是用DFS,优化则是用并查集。

例题:

洛谷P3379

传送门

这题就可以用Tarjan算法进行求解

当然,和Tarjan在一起连用的就是DFS

代码挺难的,好多:

#include<cstdio>
#include<cstring>
using namespace std;
inline int read(){
int a; scanf("%d",&a);
return a;
}
const int N=5e5+;
int head[N],n,m,S,tot(),Qtot(),f[N],ans[N],Qhead[N];
bool vis[N];
struct E{int to,next;}e[N<<];
struct Q{int ver,next;}q[N<<];
inline void add_edge(int u,int v){
e[tot]=(E){
v,head[u]
};
head[u]=tot++;
e[tot]=(E){
u,head[v]
};
head[v]=tot++;
}
inline void add_query(int u,int v){
q[Qtot]=(Q){
v,Qhead[u]
};
Qhead[u]=Qtot++;
q[Qtot]=(Q){
u,Qhead[v]
};
Qhead[v]=Qtot++;
}
inline void add_ans(int A,int query_num){
ans[query_num>>]=A;
}
void print_ans(){
for(int i=;i<m;i++)
printf("%d\n",ans[i]);
}
int find(int x){
return x==f[x]?x:f[x]=find(f[x]);
}
inline void RAB()
{
n=read();
m=read();
S=read();
int u,v;
memset(head,-,sizeof(head));
for(int i=;i<n;i++)
u=read(),v=read(),add_edge(u,v);
memset(Qhead,-,sizeof(Qhead));
for(int i=;i<=m;i++)
u=read(),v=read(),add_query(u,v);
for(int i=;i<=n;i++)
f[i]=i;
memset(vis,true,sizeof(vis));
}
void dfs(int s,int fa)
{
for(int i=head[s],to=e[i].to;i!=-;i=e[i].next,to=e[i].to)
if(to!=fa)
dfs(to,s),f[find(to)]=s;
vis[s]=false;
for(int i=Qhead[s],ver=q[i].ver;i!=-;i=q[i].next,ver=q[i].ver)
if(!vis[ver]) add_ans(find(ver),i);
}
int main()
{
RAB();
dfs(S,);
print_ans();
return ;
}

代码还没注释,为难各位了,后期我会补上的。

LCA(tarjan)的更多相关文章

  1. 【BZOJ4331】[JSOI2012]越狱老虎桥(Tarjan)

    [BZOJ4331][JSOI2012]越狱老虎桥(Tarjan) 题面 BZOJ 然而BZOJ是权限题QwQ 洛谷 题解 先求出所有割边,那么显然要割掉一条割边. 如果要加入一条边,那么显然是把若干 ...

  2. 【BZOJ2208】[JSOI2010]连通数(Tarjan)

    [BZOJ2208][JSOI2010]连通数(Tarjan) 题面 BZOJ 洛谷 题解 先吐槽辣鸡洛谷数据,我写了个\(O(nm)\)的都过了. #include<iostream> ...

  3. 浅谈强连通分量(Tarjan)

    强连通分量\(\rm (Tarjan)\)             --作者:BiuBiu_Miku \(1.\)一些术语   · 无向图:指的是一张图里面所有的边都是双向的,好比两个人打电话 \(U ...

  4. 算法详解(LCA&RMQ&tarjan)补坑啦!完结撒花(。◕ˇ∀ˇ◕)

    首先,众所周知,求LCA共有3种算法(树剖就不说了,太高级,以后再学..). 1.树上倍增(ST表优化) 2.RMQ&时间戳(ST表优化) 3.tarjan(离线算法)不讲..(后面补坑啦!) ...

  5. LCA (Tarjan&倍增)

    LCA_Tarjan 参考博客:https://www.cnblogs.com/JVxie/p/4854719.html LCA的Tarjan写法需要结合并查集 从叶子节点往上并 int Find ( ...

  6. {part1}DFN+LOW(tarjan)割点

    什么是jarjan? 1)求割点 定义:在无向连通图中,如果去掉一个点/边,剩下的点之间不连通,那么这个点/边就被称为割点/边(或割顶/桥). 意义:由于割点和割边涉及到图的连通性,所以快速地求出割点 ...

  7. HDU 3078:Network(LCA之tarjan)

    http://acm.hdu.edu.cn/showproblem.php?pid=3078 题意:给出n个点n-1条边m个询问,每个点有个权值,询问中有k,u,v,当k = 0的情况是将u的权值修改 ...

  8. Tarjan求LCA(离线)

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

  9. [HDOJ2874]Connections between cities(LCA, 离线tarjan)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2874 这题有不连通的情况,特别注意. 觉得是存query的姿势不对,用前向星存了一遍,还是T…… /* ...

随机推荐

  1. LCSS最长公共子序列算法

    0.论文基本介绍以及相关内容 分析移动用户位置的相似性,提取移动用户的相似路径在出行路径预测.兴趣区域发现.轨迹聚类.个性化路径推荐等领域具有广泛的应用. 重点:利用移动用户定位数据找到合适轨迹的表示 ...

  2. 缓存之Memcache

    Memcache Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度. ...

  3. Java中BigDecimal的舍入模式

    java.math.BigDecimal 不可变的.任意精度的有符号十进制数.BigDecimal 由任意精度的整数非标度值和32位的整数标度(scale)组成. 如果为零或正数,则标度是小数点后的位 ...

  4. vmware12启动centos6.8报错ACPI:memory_hp:Memory online failed

    报错信息 打开后出现黑屏上只显示 ACPI:memory_hp:Memory online failed for 0x10000000 - 0x80000000 BUG: soft lockup - ...

  5. js前端性能优化之函数节流和函数防抖

    前言:针对一些会频繁触发的事件如scroll.resize,如果正常绑定事件处理函数的话,有可能在很短的时间内多次连续触发事件,十分影响性能 节流: 节流:使得一定时间内只触发一次函数. 它和防抖动最 ...

  6. Github 搭建 Hexo 纯静态化个人博客平台

    以前一直想搭建一个属于自己的博客平台,有余种种原因一直未能实现,最近闲来无事,参照网上的教程,搭建了属于自己的博客.自己的博客网站,样式自由,不需要受限于各大平台. 本篇为从零开始的基础篇,本篇所包含 ...

  7. 14. Longest Common Prefix ★

    题目内容:Write a function to find the longest common prefix string amongst an array of strings 题目分析:本题目利 ...

  8. Redis安装部署教程

    1)下载 redis-3.2.9.tar.gz 2)用ssh工具连接目录主机,在命令窗口输入:mkdir -p /opt/redis创建redis文件夹 3)通过WinSCP工具将redis-3.2. ...

  9. ajax请求, 前后端, 代码示例

    [博客园cnblogs笔者m-yb原创,转载请加本文博客链接,笔者github: https://github.com/mayangbo666,公众号aandb7,QQ群927113708] http ...

  10. C语言作业(心理魔术)

    #include "stdafx.h" #include "stdio.h" #include "stdlib.h" #include &q ...