前言

\(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来实现强连通分量缩点的更多相关文章

  1. tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)

    这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...

  2. 1051: [HAOI2006]受欢迎的牛 (tarjan强连通分量+缩点)

    题目大意:CodeVs2822的简单版本 传送门 $Tarjan$强连通分量+缩点,若连通块的个数等于一则输出n:若缩点后图中出度为0的点个数为1,输出对应连通块内的点数:否则输出0: 代码中注释部分 ...

  3. Tarjan在图论中的应用(三)——用Tarjan来求解2-SAT

    前言 \(2-SAT\)的解法不止一种(例如暴搜?),但最高效的应该还是\(Tarjan\). 说来其实我早就写过用\(Tarjan\)求解\(2-SAT\)的题目了(就是这道题:[2019.8.14 ...

  4. tarjan求强连通分量+缩点+割点以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  5. Tarjan求强连通分量 缩点

    强连通分量的定义: 在一张有向图中,如果两个点u,v之间能相互到达则称这两个点u,v是强连通的,在这个基础上如果有向图G中的任意两个顶点都强连通,那么称图G是一个强连通图.有向非强连通图的极大强连通子 ...

  6. tarjan求强连通分量+缩点+割点/割桥(点双/边双)以及一些证明

    “tarjan陪伴强联通分量 生成树完成后思路才闪光 欧拉跑过的七桥古塘 让你 心驰神往”----<膜你抄>   自从听完这首歌,我就对tarjan开始心驰神往了,不过由于之前水平不足,一 ...

  7. HDU 1827 Summer Holiday(tarjan求强连通分量+缩点构成新图+统计入度+一点贪心思)经典缩点入门题

    Summer Holiday Time Limit: 10000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  8. UVA1327 && POJ1904 King's Quest(tarjan+巧妙建图+强连通分量+缩点)

    UVA1327 King's Quest POJ1904 King's Quest 题意: 有n个王子,每个王子都有k个喜欢的妹子,每个王子只能和喜欢的妹子结婚.现有一个匹配表,将每个王子都与一个自己 ...

  9. 【BZOJ1051】1051: [HAOI2006]受欢迎的牛 tarjan求强连通分量+缩点

    Description 每一头牛的愿望就是变成一头最受欢迎的牛.现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎. 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认 ...

随机推荐

  1. 51nod 1354【DP】

    (我一定是A了一题假DP) 给定序列a[0],a[1],a[2],...,a[n-1] 和一个整数K时, 有多少子序列所有元素乘起来恰好等于K. K<=1e8; 思路: 感觉 k 的 约数是突破 ...

  2. 洛谷P3396 哈希冲突(分块)

    传送门 题解在此,讲的蛮清楚的->这里 我就贴个代码 //minamoto #include<iostream> #include<cstdio> #include< ...

  3. 关于CSRF攻击详解

    CSRF的原理以及防范 CSRF概念:CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解: 攻击者盗用了你的身份,以你 ...

  4. EOS 智能合约编写(一)

    本文编写了一个简单的EOS智能合约,实现用户管理和资产管理,包括存钱,取钱,转帐的功能,旨在学习如何编写自己的EOS合约功能. 系统:Ubuntu      EOS版本:v1.1.1 一.智能合约代码 ...

  5. k8s 更新应用程序

    参考:https://kubernetes.io/docs/tutorials/kubernetes-basics/ 更新应用程序 用户希望应用程序始终可用,开发人员每天需要部署几次新版本的应用程序. ...

  6. 读书笔记 - 《梦想与浮沉:A股十年上市博弈》

    拿到这本书是个很偶然的事件.有几本软件业书由于太老已经绝版,偶然想到小区的图书馆自动借阅机和读者证的预借功能,就兴冲冲的跑去尝试.没想到预借只能在网页上进行,就随手从机器里借了这本书.没想到细观之下让 ...

  7. win10卸载更新+关闭自动更新的方法

    卸载更新方法:  左下角->设置->更新和安全->windows更新->高级选项->查看更新历史记录->卸载更新 关闭自动更新的方法:win+r 输入service ...

  8. drools的error:Jboss rule 6.4.0 Cannot find a default StatelessKieSession

    drools的kmodule.xml文件,如果是默认加载必须放在META-INF的文件夹下,如下图 官网大佬原话 Have you defined kieSession and KieBase nam ...

  9. java反射-使用反射获取类的所有信息

    在OOP(面向对象)语言中,最重要的一个概念就是:万事万物皆对象. 在java中,类也是一个对象,是java.lang.Class的实例对象,官网称该对象为类的类类型. Class 类的实例表示正在运 ...

  10. JVM虚拟机 - 内存

    在JVM虚拟机中,内存部分大致可以分为以下几类: Heap:堆 NonHeap:非堆 CodeCache:缓存编辑后的机器码的内存区域 CompressedClassSpace:类压缩空间 MetaS ...