Tarjan在图论中的应用(一)——用Tarjan来实现强连通分量缩点
前言
\(Tarjan\)是一个著名的将强连通分量缩点的算法。
大致思路
它的大致思路就是在图上每个联通块中任意选一个点开始进行\(Tarjan\)操作(依据:强连通分量中的点可以两两到达,因此从任意一个点开始都没关系)。
具体实现
对于每一个点,先记录它的\(dfs\)序,并将该点加入一个栈中,并标记其在栈中,然后用\(low[]\)数组来记录从它出发能到达的字典序最小的节点。
枚举它所能到达的每一个节点,并对每一个节点进行分类讨论:
设当前节点为\(x\),枚举到的节点为\(son\)。
如果\(son\)没有被访问过,就先对它进行Tarjan操作,然后更新\(low[x]\)(\(low[x]=min(low[x],low[son])\))。
如果\(son\)已经被访问过,又分两种情况:
如果\(son\)在栈中,那么更新\(low[x]\)。
如果\(son\)不在栈中,那么代表已经对\(son\)所能到达的每一个节点操作过,说明从\(son\)不能到达\(x\),即它们不在同一个强连通分量中,因此不能更新\(low[x]\)。
在枚举完每一个节点后,我们可以判断当前节点是否就是它能到达的dfs序最小的节点,如果是的话,说明它是一个强连通分量中最早被访问过的(当然,也有可能说明它所在的强连通分量中就只有它一个节点),否则,就说明还有比它更早被访问过的,那么退出函数。
如果当前节点是一个强连通分量中最早被访问到的,那么就说明栈中在它上面的节点全都和它在一个强连通分量中,我们可以新建一个强连通分量,并将它连同在它上面的点全部加入这个强连通分量中即可(加入的同时要注意更新这个强连通分量的信息,可参考例题)。
代码
inline void Tarjan(int x)//x是当前访问到的节点
{
dfn[x]=low[x]=++d,Stack[++top]=x,vis[x]=1;//记录当前节点的dfs序与当前节点所能到达的dfs序最小的点,将当前节点加入栈中,并标记当前节点在栈中
for(register int i=lnk[x];i;i=e[i].nxt)//枚举从当前节点出发的每一条边
{
if(!dfn[e[i].to]) Tarjan(e[i].to),low[x]=min(low[x],low[e[i].to]);//如果这个节点没访问过,就先对这个节点进行操作,然后更新当前节点能到达的dfs序最小的点
else if(vis[e[i].to]) low[x]=min(low[x],low[e[i].to]);//否则,如果这个点在栈中,就进行更新
}
if(low[x]==dfn[x])//如果当前节点就是当前节点能到达的dfs序最小的点,则对当前强连通分量进行缩点
{
a[x].col=++cnt,vis[x]=0;//给当前节点加入一个新的强连通分量,并标记当前节点已出栈(如果需要,还要初始化这个强连通分量的信息,可参考例题)
while(Stack[top]^x) a[Stack[top]].col=cnt,vis[Stack[top--]]=0;//将栈中当前节点之上的节点一一弹出(如果需要,还要同时更新这个强连通分量的信息)
--top;//将当前节点弹出
}
}
例题
例题1:【洛谷2403】[SDOI2010] 所驼门王的宝藏
例题2:【51nod1815】调查任务
Tarjan在图论中的应用(一)——用Tarjan来实现强连通分量缩点的更多相关文章
- tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)
这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...
- 1051: [HAOI2006]受欢迎的牛 (tarjan强连通分量+缩点)
题目大意:CodeVs2822的简单版本 传送门 $Tarjan$强连通分量+缩点,若连通块的个数等于一则输出n:若缩点后图中出度为0的点个数为1,输出对应连通块内的点数:否则输出0: 代码中注释部分 ...
- Tarjan在图论中的应用(三)——用Tarjan来求解2-SAT
前言 \(2-SAT\)的解法不止一种(例如暴搜?),但最高效的应该还是\(Tarjan\). 说来其实我早就写过用\(Tarjan\)求解\(2-SAT\)的题目了(就是这道题:[2019.8.14 ...
- tarjan求强连通分量+缩点+割点以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- Tarjan求强连通分量 缩点
强连通分量的定义: 在一张有向图中,如果两个点u,v之间能相互到达则称这两个点u,v是强连通的,在这个基础上如果有向图G中的任意两个顶点都强连通,那么称图G是一个强连通图.有向非强连通图的极大强连通子 ...
- tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明
“tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄> 自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...
- HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题
Summer Holiday Time Limit: 10000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- UVA1327 && POJ1904 King's Quest(tarjan+巧妙建图+强连通分量+缩点)
UVA1327 King's Quest POJ1904 King's Quest 题意: 有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚.现有一个匹配表,将每个王子都与一个自己 ...
- 【BZOJ1051】1051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点
Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认 ...
随机推荐
- git 修改远程仓库源
自己已经写好了一个项目,想上传到 github github 创建新项目 新建 README.md , LICENSE 本地项目添加 github 远程仓库源 不是git项目 git remote a ...
- 【转】processOnServer
源地址:http://blog.csdn.net/dl020840504/article/details/8856853
- 洛谷P1310 表达式的值
P1310 表达式的值 题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例 ...
- 洛谷P3396 哈希冲突(分块)
传送门 题解在此,讲的蛮清楚的->这里 我就贴个代码 //minamoto #include<iostream> #include<cstdio> #include< ...
- IO模式和IO多路复用详解
网络编程里常听到阻塞IO.非阻塞IO.同步IO.异步IO等概念,总听别人装13不如自己下来钻研一下.不过,搞清楚这些概念之前,还得先回顾一些基础的概念. 1 基础知识回顾 注意:咱们下面说的都是Lin ...
- springBoot2.0 配置 mybatis+mybatisPlus+redis
一.Idea新建springBoot项目 next到完成,然后修改使用自己的maven 等待下载包 二.pom.xml文件 <?xml version="1.0" encod ...
- lynis检测
https://www.cnblogs.com/ssooking/p/6034402.html Usage: lynis command [options] Command: audit audit ...
- java 集合解析
Set集合,放的元素不能重复,请问它的判断重不重复是怎么实现的? 比如说:ArrayList 和 Vector 是用数组的方式存储的Set里的 hashSet 和TreeSet是用什么方式存储的?怎么 ...
- Dijkstra算法(求一点到任意一点的最短距离)
思路:先找出最短的一个点,也就是起点,从起点出发,找最短的边,同时标记起点为true(代表已经访问过),访问过的点就不用再访问了,依次下去,保证每一次找到的边都是最短的边 到最后没有边可以更新了就代表 ...
- Unity Unity脚本类为什么要尽量避免继承MonoBehaviour类?