这是一种离线算法,但是时间超级快,是O(n+m)。
主要是dfs实现这个过程。

下面详细介绍一下Tarjan算法的基本思路:
1.任选一个点为根节点,从根节点开始。
2.遍历该点u所有子节点v,并标记这些子节点v已被访问过。
3.若是v还有子节点,返回2,否则下一步。
4.合并v到u上。
5.寻找与当前点u有询问关系的点v。
6.若是v已经被访问过了,则可以确认u和v的最近公共祖先为v被合并到的父亲节点a。
遍历的话需要用到dfs来遍历(我相信来看的人都懂吧…),至于合并,最优化的方式就是利用并查集来合并两个节点。
(以上转载自:blog)

由于我太弱,无法完整讲述算法精髓,大家要是没懂就去看那个blog吧。
这个dfs代码是我自已YY了一部分,借鉴题解一部分。
代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline void read(int &x){char ch=' ';while(!isdigit(ch=getchar()));x=ch-'0';while(isdigit(ch=getchar())){x=x*10+ch-'0';}
}
struct Q{int y,id,next;
}q[1000001];
struct edge{int to,next;
}e[1000001];
int n,m,s,tot,tot_ask;
int head_ask[500001];
int fa[500001];
int vis[500001];
int ans[500001];
int head[500001];
inline void addedge(int x,int y){tot++;e[tot].to=y;e[tot].next=head[x];head[x]=tot;
}
inline void addask(int x,int y,int id){tot_ask++;q[tot_ask].y=y;q[tot_ask].next=head_ask[x];head_ask[x]=tot_ask;q[tot_ask].id=id;
}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);
}
void dfs(int u,int father){for(int i=head[u];i;i=e[i].next){int v=e[i].to;if(v!=father){dfs(v,u);fa[v]=u;}}vis[u]=1;for(int i=head_ask[u];i;i=q[i].next){int v=q[i].y;if(vis[v]){ans[q[i].id]=find(v);}}
}
int main(){read(n);read(m);read(s);for(int i=1;i<=n-1;i++){int x,y;read(x);read(y);addedge(x,y);addedge(y,x);}for(int i=1;i<=n;i++){fa[i]=i;}for(int i=1;i<=m;i++){int x,y;read(x);read(y);addask(x,y,i);addask(y,x,i);}dfs(s,0);for(int i=1;i<=m;i++){printf("%d\n",ans[i]);}return 0;
}

转载于:https://www.cnblogs.com/stone41123/p/7581270.html

图论--tarjan求lca相关推荐

  1. 洛谷 - P3379 【模板】最近公共祖先(LCA)(RMQ求LCA/Tarjan求LCA)

    题目链接:点击查看 题目大意:给出一棵 n 个点组成的有根树,再给出 m 次询问,每次询问需要回答点 x 和点 y 的 lca 题目分析:今天新学了两种蛮有意思的求 LCA 的方法,总结一下四种方法各 ...

  2. Tarjan求lca

    https://vjudge.net/problem/POJ-1330 是到水的题,简单点在于其只需求一对lca即可,这是比较简单的. 主要看了以下blog http://blog.csdn.net/ ...

  3. tarjan求LCA模板

    废话不多说,模板拿来. 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # ...

  4. 《信息学奥赛一本通 提高篇》 第四部分 数据结构 第4章 倍增求LCA

    例题1 点的距离 信息学奥赛一本通(C++版)在线评测系统 例题2 暗的连锁(Poj3417) 信息学奥赛一本通(C++版)在线评测系统 LOj10131 暗的连锁_juruo_xlh-CSDN博客 ...

  5. 【Gym - 101986F】Pizza Delivery(Dijkstra最短路,建图方式,反向建图,Tarjan求桥,图论模板)

    题干: 题目大意: 一个有向图,编号1~n的n个点,m条边,规定1为起点,2为终点,问对于每一条边,反转它的方向,最短路会不会发生改变,如果变短了,输出HAPPY,变长了或者到达不了了输出SAD,不变 ...

  6. 图论 —— 图的连通性 —— Tarjan 求双连通分量

    [概念] 1.双连通分量:对于一个无向图,其边/点连通度大于1,满足任意两点之间,能通过两条或两条以上没有任何重复边的路到达的图,即删掉任意边/点后,图仍是连通的 2.分类: 1)点双连通图:点连通度 ...

  7. 图论 —— 图的连通性 —— Tarjan 求割点与桥

    [概念] 1.割点 1)割点:删除某点后,整个图变为不连通的两个部分的点 2)割点集合:在一个无向图中删除该集合中的所有点,能使原图变成互不相连的连通块的点的集合 3)点连通度:最小割点集合点数 如上 ...

  8. [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)

    [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...

  9. 牛客 - 牛半仙的妹子Tree(按询问分块+RMQ求LCA)

    题目链接:点击查看 题目大意:给出一棵有 n 个节点的树,需要执行 m 次操作: 1 x:点 x 被染色,且随后每一秒染色的区域都会向外扩展一个单位 2 x:清空所有的染色 3 x:问点 x 是否被染 ...

最新文章

  1. [bbk4966]第70集 第8章 -性能维护 01
  2. Nature子刊:Salmon不比对快速宏基因组基因定量
  3. DeviceEventEmitter 使用监听通知进行传值
  4. Linux静态/动态链接库的创建和使用
  5. Java中的字符串常量池详细介绍
  6. java super用法_Java基础面试题汇总
  7. python序列操作_操作序列(python)
  8. 【sketchup 2021】草图大师图像输出与渲染之Enscape渲染(优秀的实时渲染软件)的安装与软件说明,并在sketchup软件中调出Enscape软件和使用。
  9. 运放输入偏置电流方向_运算放大器+仪表放大器:如何为偏置电流提供直流回路?...
  10. 纳米磁珠+AI:让液体活检越走越近
  11. 【学习笔记】无限极分类学习
  12. 让16位Pwin3.2程序在64位Win10上跑起来
  13. maven jar包瘦身
  14. 机器自动翻译古文拼音 - 十大宋词 - 如梦令·昨夜雨疏风骤 李清照
  15. 面对新时代挑战,2019维谛技术峰会全面呈献硬核策略
  16. 蓝牙设备通过手机空中升级固件步骤
  17. 音视频测试测的究竟是什么
  18. 2021-10-26尤破金10.27外汇黄金白银实时操作策略布局
  19. 预测神经胶质瘤基因型的多模态学习
  20. 面试中常被问到的(17)多线程及多进程优缺点

热门文章

  1. Android设备新型恶意软件,融合银行木马、键盘记录器和移动勒索软件等功能
  2. python glob模块的应用
  3. ecshop调用文章显示上一篇下一篇_无需整理
  4. 在Windows Server 2008中安装Exchange Server 2007 SP1
  5. 图片资源添加出现问题: No resource found that matches the given name
  6. 12 个有效的提高编程技能的方法
  7. eas之Uuid和BOSUuid 区别
  8. 程序员必备技能-科学砍需求 1
  9. RxSwift中Observable的各种创建方法
  10. 记腾讯一面 | 掘金技术征文