1.前言

  首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为)。

2.思想

  下面详细介绍一下Tarjan算法的思想:

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

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

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

      4.合并v到u上。

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

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

  从上面步骤可以看出,Tarjan算法要用到并查集。这里,我们使用链式前向星来存储边和询问情况。

3.算法实现

不妨以洛谷P3379:LCA模板题为例题

 #include<cstdio>
#include<cstring> const int maxn = 5e5 + ,maxm = 5e5 + ;
int fa[maxn],fir[maxn],frt[maxn],ans[maxm],n,m,s,tot,id;
bool flag[maxn];
//存边
struct Edge{
int v,next;
}e[maxn << ];
//存询问
struct Ques{
int v,next,qid;
}q[maxm << ];
//加边
void addEdge(int u,int v){
e[tot] = (Edge){v,fir[u]};
fir[u] = tot++;
e[tot] = (Edge){u,fir[v]};
fir[v] = tot++;
}
//加询问
void addQues(int u,int v,int qid){
q[id] = (Ques){v,frt[u],qid};
frt[u] = id++;
q[id] = (Ques){u,frt[v],qid};
frt[v] = id++;
}
//读入优化
inline int read(){
int sum = ;
char ch = getchar();
while(ch < '' || ch > '') ch = getchar();
while(ch >= '' && ch <= ''){sum = sum * + ch - ''; ch = getchar();}
return sum;
}
//输出优化
void write(int x){
if(x / ) write(x / );
putchar(x % + '');
}
//寻找父亲
int find(int x){
if(fa[x] != x) fa[x] = find(fa[x]);
return fa[x];
}
//合并
void unionn(int x,int y){
int fx = find(x),fy = find(y);
fa[fx] = fy;
}
//离线操作(u表示当前点,fa表示该点的前驱点)
void dfs(int u,int fa){
flag[u] = true;//标记已访问
//遍历所有与u相连的点
for(int i = fir[u];i != -;i = e[i].next){
int v = e[i].v;
//如果v不是u的前驱
if(v != fa){
dfs(v,u);//遍历下一层
//寻找是否有询问关系
for(int j = frt[v];j != -;j = q[j].next){
int k = q[j].v;
if(flag[k])
ans[q[j].qid] = find(k);
}
unionn(v,u);//连接
}
}
}
//主函数
int main(){
n = read(),m = read(),s = read();
memset(fir,-,sizeof(fir));
memset(frt,-,sizeof(frt));
for(int i = ;i < n;i++){
fa[i] = i;
int x = read(),y = read();
addEdge(x,y);
}
fa[n] = n;
for(int i = ;i <= m;i++){
int x = read(),y = read();
addQues(x,y,i);
}
dfs(s,-);
//因为这里已经给出根了,直接从根开始
for(int i = ;i <= m;i++,putchar('\n')) write(ans[i]);
return ;
}

  

TarjanLCA学习笔记的更多相关文章

  1. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  2. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  3. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  4. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  5. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

  6. seaJs学习笔记2 – seaJs组建库的使用

    原文地址:seaJs学习笔记2 – seaJs组建库的使用 我觉得学习新东西并不是会使用它就够了的,会使用仅仅代表你看懂了,理解了,二不代表你深入了,彻悟了它的精髓. 所以不断的学习将是源源不断. 最 ...

  7. CSS学习笔记

    CSS学习笔记 2016年12月15日整理 CSS基础 Chapter1 在console输入escape("宋体") ENTER 就会出现unicode编码 显示"%u ...

  8. HTML学习笔记

    HTML学习笔记 2016年12月15日整理 Chapter1 URL(scheme://host.domain:port/path/filename) scheme: 定义因特网服务的类型,常见的为 ...

  9. DirectX Graphics Infrastructure(DXGI):最佳范例 学习笔记

    今天要学习的这篇文章写的算是比较早的了,大概在DX11时代就写好了,当时龙书11版看得很潦草,并没有注意这篇文章,现在看12,觉得是跳不过去的一篇文章,地址如下: https://msdn.micro ...

随机推荐

  1. 上下文管理器 contextlib

    from contextlib import contextmanager @contextmanager def tag(name): print "<%s>" % ...

  2. Java应用调试利器——BTrace教程

    http://www.jianshu.com/p/26f19095d396 背景 生产环境中可能出现各种问题,但是这些问题又不是程序error导致的,可能是逻辑性错误,这时候需要获取程序运行时的数据信 ...

  3. 【NOIP】提高组2015 斗地主

    [题意]按照斗地主出牌规则,给定手牌求出完的最少步数. [算法]模拟+搜索 [题解] 可以发现除了顺子,其它的出牌规则都和点数无关,只与同点数的牌数有关. 所以可以先暴力枚举要出哪些顺子,然后每一个出 ...

  4. LESS使用简介!

    我真的真的极度痛苦. 原本用了那么久的LESS,一直都是用编译工具(考拉)进行编译的,今天试了试用less.js来搞,按官网的都一毛一样,然而!就是编译不出来! 我用来擦鼻涕的卫生纸都一下午用了大半卷 ...

  5. Spring Cloud与Spring Boot的关系

    1.Spring Cloud是一个工具集:Spring   Cloud是在Spring    Boot的基础上构建的,用于简化分布式系统构建的工具集:使架构师在创建和发布微服务时极为便捷和有效. Sp ...

  6. Perl6 Bailador框架(3):路径匹配

    use v6; use Bailador; =begin pod 注意的是, 当/:one设置时 虽然你有/admin或/about, 但这个/:one不会跟现有的匹配 只跟没有的匹配: 也就是说, ...

  7. devm_xxx机制

    前言 devm是内核提供的基础机制,用于方便驱动开发者所分配资源的自动回收.参考内核文档devres.txt.总的来说,就是驱动开发者只需要调用这类接口分配期望的资源,不用关心释放问题.这些资源的释放 ...

  8. Android IPC

    1. 什么是Android IPC IPC:inter-process Commnication跨进程的通信,多进程之间的通信,不同的操作系统有不同的通信方式,Android继承自Linux,但其IP ...

  9. 微信小程序验证码获取倒计时

    wxml <button disabled='{{disabled}}' bindtap="goGetCode">{{code}}</button> js ...

  10. js对页面对float类型的数据格式化处理

    <script>        document.write(parseFloat(<s:property value="assureterm"/>)); ...