[算法模版]Tarjan爷爷的几种图论算法

前言

Tarjan爷爷发明了很多图论算法,这些图论算法有很多相似之处(其中一个就是我都不会)。这里会对这三种算法进行简单介绍。

定义

强连通(strongly connected): 在一个有向图\(G\)里,设两个点a, b 发现,由\(a\)有一条路可以走到\(b\),由\(b\)又有一条路可以走到\(a\),我们就叫这两个顶点(a,b)强连通。

强连通图: 如果 在一个有向图\(G\)中,每两个点都强连通,我们就叫这个图,强连通图。

分量:把一个向量分解成几个方向的向量的和,那些方向上的向量就叫做该向量(未分解前的向量)的分量。

强连通分量(strongly connected components/SCC):在一个有向图G中,有一个子图,这个子图每2个点都满足强连通,我们就叫这个子图叫做强连通分量。

比如说这个图,在这个图中呢,点1与点2互相都有路径到达对方,所以它们强连通。

而在这个有向图中,点1 2 3组成的这个子图,是整个有向图中的强连通分量。

dfn[i]:指第\(i\)个点的\(dfs\)序。

low[i]:指第\(i\)个点的子树内的所有点通过反祖边能走到的点的\(dfn\)的最小值。

先行结论

  • 在一个无向图上,跑一棵生成树。可以证明非树边只有反祖边,没有横叉边。

Tarjan算法求割点/割边(针对无向图)

割点

首先,一个比较显然的结论就是所有的叶子结点和根节点都不是割点。对于其他节点u来说,只要有至少一个儿子v满足low[u]>=dfn[v],就证明v若不通过他父亲就回不去。那这个点就是割点。根节点只需要判断是不是有两棵子树就好了。实现起来可以当作有两个点满足low[u]>=dfn[b]。因为因为根节点\(dfn\)为1,所以一定满足条件。如果两个根结点儿子不通过根节点就能联通,那么他们一定在一个子树。

void tarjan(int now,int ff){
low[now]=dfn[now]=++idx;
for(int i=head[now];i;i=side[i].next){
int v=side[i].v;
if(side[i].id==ff)continue;
if(!dfn[v]){
tarjan(v,side[i].id);
low[now]=min(low[now],low[v]);
if(low[v]>=dfn[now]){ans[now]++;}
}
else{
low[now]=min(dfn[v],low[now]);
}
}
return;
}
void output(){
for(int i=1;i<=n;i++){
if((ans[i]&&!root[i])||(ans[i]>=2&&root[i])){
cout<<i<<' ';//输出所有割点
}
}
}

割边

和割点基本一样。只需要把\(low[v]>=dfn[u]\)改成\(low[v]>dfn[u]\)即可。同时需要判断,不能再次走刚刚走过的边。

如果点u的至少一个儿子v满足low[v]>dfn[u]。就证明不通过这条边无法走到上面。所以这是条割边。

Tarjan算法求点双/边双(针对无向图)

边双

和楼下的强连通分量很像,唯一的区别就是需要特殊判断一下,不能通过从父亲下来的那条边走上去。(因为强连通分量是有向图,走不上去,所以不存在这个问题)

实现起来也很简单,只用简单修改一下dfs函数:

dfs(u,f)其中u为当前节点,f为走到这个点通过的边的编号。

当在遍历u的所有边试图向下dfs时,只需要加一个if(现在准备选择的边的编号==f)continue;即可。

点双

咕咕咕

Tarjan算法求强连通分量(针对有向图)

stack<int> tp;
void dfs(int u)
{
dfn[u]=low[u]=++cnt1;//初始化每个未访问过的节点
tp.push(u);
for(int i=head[u];i;i=side[i].next)
{
int v=side[i].v;
if(!dfn[v])dfs(v),low[u]=min(low[u],low[v]);
else if(!scc[v])low[u]=min(low[u],dfn[v]);//被访问过却没有SCC编号(在栈里),证明在同一个强连通分量。因为栈维护的是一条有一个节点到它儿子的路径。所以如果栈顶的点u到栈中任意一点v有边。就证明存在u到v的一个环。
}
if(dfn[u]==low[u])//如果这个点是它所在强连通分量中dfn最小的,则有它来承担输出整个SCC的任务
{
int s=tp.top(),id=++cnt2;tp.pop();
scc[s]=id;
while(s!=u)s=tp.top(),tp.pop(),scc[s]=id;
}
}

参考资料

全网最!详!细!Tarjan算法讲解

割点和桥

[算法模版]Tarjan爷爷的几种图论算法的更多相关文章

  1. java开发过程中几种常用算法

    排序算法 排序算法中包括:简单排序.高级排序 简单排序 简单排序常用的有:冒泡排序.选择排序.插入排序 冒泡排序代码如下: private static void bubbleSrot(int[] a ...

  2. Java 的八种排序算法

    Java 的八种排序算法 这个世界,需要遗忘的太多. 背景:工作三年,算法一问三不知. 一.八种排序算法 直接插入排序.希尔排序.简单选择排序.堆排序.冒泡排序.快速排序.归并排序和基数排序. 二.算 ...

  3. 图论算法-Tarjan模板 【缩点;割顶;双连通分量】

    图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...

  4. 图论算法》关于tarjan算法两三事

    关于tarjan,在下觉得这个算法从本质上是一种暴力求强连通分量的方法,但事实上这也是最有效的求强连通分量的方法之一,它对于处理各种强连通分量中奇怪问题,都可以直接转化,所以比较通用和常见. 什么是t ...

  5. tarjan图论算法

    tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...

  6. LCA算法解析-Tarjan&倍增&RMQ

    原文链接http://www.cnblogs.com/zhouzhendong/p/7256007.html UPD(2018-5-13) : 细节修改以及使用了Latex代码,公式更加美观.改的过程 ...

  7. Kosaraju算法、Tarjan算法分析及证明--强连通分量的线性算法

    一.背景介绍 强连通分量是有向图中的一个子图,在该子图中,所有的节点都可以沿着某条路径访问其他节点.强连通性是一种非常重要的等价抽象,因为它满足 自反性:顶点V和它本身是强连通的 对称性:如果顶点V和 ...

  8. 对比几种在ROS中常用的几种SLAM算法

    在此因为要总结写一个文档,所以查阅资料,将总结的内容记录下来,欢迎大家指正! 文章将介绍使用的基于机器人操作系统(ROS)框架工作的SLAM算法. 在ROS中提供的五种基于2D激光的SLAM算法分别是 ...

  9. JVM的分区+查看GC对象是否存活+3种GC算法+7种垃圾收集器+如何减少GC次数

    一.JVM的分区:   1.程序计数器(私有) 程序计数器是一块较小的内存分区,你可以把它看做当前线程所执行的字节码的指示器. 在虚拟机的概念模型里,字节码解释器工作时,就是通过改变计数器的值来选择下 ...

随机推荐

  1. 【LGR-061】洛谷10月月赛 II & X Round 4 Div.1&Div 2

    X Round的题目质量还是一如既往的高 然而每次周末我都要写作业没法用心打233主要是被陈指导放了鸽子 占坑代填(最近坑开的有点多)

  2. Python必备收藏!博士大佬总结的Pycharm 常用快捷键思维导图

    ​ 搜索 Ctrl + Shift + F7用法高亮显示 Ctrl + Alt + F7显示用法 编辑 ​ Ctrl + Shift + V从最近的缓冲区粘贴 Ctrl + D复制选定的区域或行到后面 ...

  3. Loj #6503. 「雅礼集训 2018 Day4」Magic

    Loj #6503. 「雅礼集训 2018 Day4」Magic 题目描述 前进!前进!不择手段地前进!--托马斯 · 维德 魔法纪元元年. 1453 年 5 月 3 日 16 时,高维碎片接触地球. ...

  4. 打印从1到最大的n

    题目:输入数字n,按顺序打印出从1到最大的n位十进制数.比如输入3,则打印出1.2.3一直到最大的3位数999 需考虑大数问题 #-*-coding:utf-8-*- class print_N: d ...

  5. IT兄弟连 Java语法教程 流程控制语句 控制循环结构1

    Java语言没有提供goto语句来控制程序的跳转,这种做法提高了程序流程控制的可读性,但降低了程序流程控制的灵活性.为了弥补这种不足,Java提供了continue和break来控制循环结构.除此之外 ...

  6. ASP.NET(1)

    1.IIS安装问题,先装VS再装IIS,处理程序映射有问题,使用VS自带的控制台输入命令,注册路径 2.开发模式,一般处理程序,使用IO操作读取html文件,使前后端分离 3.post请求和get请求 ...

  7. python爬取网站视频保存到本地

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: Woo_home PS:如有需要Python学习资料的小伙伴可以加点 ...

  8. Flask 教程 第三章:Web表单

    本文翻译自 The Flask Mega-Tutorial Part III: Web Forms 这是Flask Mega-Tutorial系列的第三部分,我将告诉你如何使用Web表单. 在第二章中 ...

  9. 1-4-JS基础-条件判断

    第一种 1.if(条件成立){ 执行某件事} 2.if(条件成立){执行某件事}else{执行另外一件事 } 3.if(条件1成立){执行某件事}else if(条件2成立){执行某件事}else i ...

  10. 版本管理·玩转git(分支管理)

    在开发中,遇到这样的情况怎么办? 网站已有支付宝在线支付功能,要添加"微信支付",修改了两个文件,wechat.php.pay.php. 刚做到一半,突然有个紧急bug:支付宝支付 ...