前言

图论中联通性相关问题往往会牵扯到无向图的割点与桥或是下一篇博客会讲的强连通分量,强有力的\(Tarjan\)算法能在\(O(n)\)的时间找到割点与桥

定义

若您是第一次了解\(Tarjan\)算法,建议您反复阅读定义,借助图像来理解

  • 桥与割边

对于无向连通图中点集的一个节点\(x\),删去节点\(x\)及其关联的边之后,存在一对不联通的点对\((a,b)\),则称\(x\)是这个无向图的割点

对于无向联通图中边集的一条边\(e\),删去边\(e\)之后,存在一对不联通的点对\((a,b)\),则称\(x\)是这个无向图的桥或割边

对于一般无向图,割点和桥可以指各个联通块的割点和桥

  • 时间戳:

在对图的\(DFS\)中,按照节点第一次被访问的顺序,给各个节点标记一个值,该值称为时间戳,我们用\(dfn[x]\)表示\(x\)的时间戳

  • 搜索树

在对图的\(DFS\)中,由于每个点只会被搜一次,所以访问经过的边构成了一棵树,称为搜索树,各个节点为根的子树称为\(subtree(x)\),注意,\(x \in subtree(x)\)

  • 追溯值

这个可以说是\(Tarjan\)算法的精髓了,在我个人看来,节点\(x\)的追溯值是指不经搜索树所能到达的所有节点中其时间戳的最小值或者它自身的时间戳.

这看起来很难得到各个节点的追溯值,实则不然,分析一下,节点\(x\)的追溯值可以在一遍\(DFS\)中求得,请看下文介绍

算法

  • 性质一: 桥边都是搜索树上的边

    反证法,若桥边不是搜索树上的边,断掉这条之后仍可通过搜索树上的边保持图的联通

  • 割边判定法则

    无向边\((x,y)\)是桥的充要条件是\(dfn[x]<low[y]\)(假设\(y \in subtree(x)\))

    让我们想想为什么

    \(low[y]\)表示不经搜索树上的边\(y\)所能到达的所有节点中其时间戳的最小值,若\(dfn[x]<low[y]\),根据定义和性质一,说明只有这条在s搜索树上的边\((x,y)\) ,\(y\)才能到达\(x\),故边\((x,y)\)是桥(割边)

  • 割点判定法则

    非根点\(x\)是割点的充要条件是存在一点\(y (y \in subtree(x))\),满足\(dfn[x]<=low[y]\),类比于上一法则,这里不再赘述

    当\(x\)为根节点时至少要有两个点满足上述条件

注意

  1. 更新\(low[x]\)

    根据定义,我们只能用\(x\)在搜索树上儿子的\(low[]\)值或是一条非搜索树边\((x,y)\)中的\(dfn[y]\)来更新\(low[x]\)

  2. 重边

    在求桥时,若节点\(x\)与其父亲间有重边,则其中只有一条算搜索树上的边,其他都是非搜索树上的边,可以用来更新.

    然而求割点时,由于是点与点联通关系不必考虑重边

代码

  • 桥
int dfn[maxn],low[maxn],cnt=0;
bool bridge[maxm];
void tarjan(int u,int in_edge){//in_edge--边的编号
int v;dfn[u]=low[u]=++cnt;
for(ri i=h[u];i;i=edge[i].ne){
v=edge[i].to;
if(!dfn[v]){
tarjan(v,i);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]){
bridge[i]=bridge[i^1]=1;
}
}
else if(i!=(in_edge^1)){
//in_edge^1表示反向边,不是反向边说明是非搜索树边
low[u]=min(low[u],dfn[v]);//通过非树边更新
}
}
return ;
}
  • 缩点
int dfn[maxn],low[maxn],root,tot=0;
bool ans[maxn];
void tarjan(int now){
int v,flag=0;dfn[now]=low[now]=++tot;
for(ri i=h[now];i;i=edge[i].ne){
v=edge[i].to;
if(!dfn[v]){
tarjan(v);
low[now]=min(low[now],low[v]);
if(dfn[now]<=low[v]){
flag++;
if(now!=root||flag>1)//根节点要有两个满足条件
{
if(!ans[now])ans[now]=1;//是割点
}
}
}
else low[now]=min(low[now],dfn[v]);
}
return ;
}

例题

学习笔记--Tarjan算法之割点与桥的更多相关文章

  1. [学习笔记] Tarjan算法求桥和割点

    在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥.割点,也是和上篇有博客有类似之处的. 关于桥和割点: 桥:在一个有向图中,如果删去一条边,而 ...

  2. [学习笔记] Tarjan算法求强连通分量

    今天,我们要探讨的就是--Tarjan算法. Tarjan算法的主要作用便是求一张无向图中的强连通分量,并且用它缩点,把原本一个杂乱无章的有向图转化为一张DAG(有向无环图),以便解决之后的问题. 首 ...

  3. Tarjan的学习笔记 求割边求割点

    博主图论比较弱,搜了模版也不会用... 所以决心学习下tarjan算法. 割点和割边的概念不在赘述,tarjan能在线性时间复杂度内求出割边. 重要的概念:时间戟,就是一个全局变量clock记录访问结 ...

  4. Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂

    更好的阅读体验&惊喜&原文链接 感谢@yxc的腿部挂件 大佬,指出本文不够严谨的地方,万分感谢! Tarjan无向图的割点和桥(割边) 导言 在掌握这个算法前,咱们有几个先决条件. [ ...

  5. [ML学习笔记] XGBoost算法

    [ML学习笔记] XGBoost算法 回归树 决策树可用于分类和回归,分类的结果是离散值(类别),回归的结果是连续值(数值),但本质都是特征(feature)到结果/标签(label)之间的映射. 这 ...

  6. tarjan算法求无向图的桥、边双连通分量并缩点

    // tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...

  7. Tarjan算法求割点

    (声明:以下图片来源于网络) Tarjan算法求出割点个数 首先来了解什么是连通图 在图论中,连通图基于连通的概念.在一个无向图 G 中,若从顶点i到顶点j有路径相连(当然从j到i也一定有路径),则称 ...

  8. [Tarjan系列] Tarjan算法求无向图的桥和割点

    RobertTarjan真的是一个传说级的大人物. 他发明的LCT,SplayTree这些数据结构真的给我带来了诸多便利,各种动态图论题都可以用LCT解决. 而且,Tarjan并不只发明了LCT,他对 ...

  9. tarjan算法应用 割点 桥 双连通分量

    tarjan算法的应用. 还需多练习--.遇上题目还是容易傻住 对于tarjan算法中使用到的Dfn和Low数组. low[u]:=min(low[u],dfn[v])--(u,v)为后向边,v不是u ...

随机推荐

  1. mysql zip方式安装

    下载zip文件解压到安装目录,此时是没有data文件夹和my.ini文件的. 1.首先自己新建my.ini,内容如下: [client] port=3306 default-character-set ...

  2. Docker Image

    Docker 对 container 的使用基本是建立在 LXC 基础之上,然而 LXC 存在的问题是难以移动,难以通过标准化的模板去制作.重建.复制和移动 container. 在以 VM 为基础的 ...

  3. DataFactory生产手机号码

    表中的数据类型是CHAR()类型的,才会出现,如右图的“Build a composite field”的这个功能: 固定部分设置 剩余变化部分设置 操作成功 数据库查询的结果

  4. vue-图片预览,查看大图

    [前言] 在 vue 项目中经常碰到图片预览需求,也就是点击小图查看大图.也有一些这样的第三方插件,如 vue-preview 等.但使用起来感觉版本经常变,而且有时 UI 需要在预览页面上加更多的东 ...

  5. harber私有镜像仓库(4)

    一.部署准备: 准备harbor软件包 在部署节点上: #mv harbor-offline-installer-v1.4.0.tgz /opt/ && cd /opt #tar zx ...

  6. Python-sympy科学计算与数据处理(数学表达式)

    数学表达式 from sympy import * 1/2+1/3 S(1)/2+1/S(3) Out[4]: 5/6 Rational(5,10) Out[5]: 1/2 x,y = symbols ...

  7. delphi循环校验数据集

    function XXXXXFrom.CheckData(Sender: TObject): Boolean; var tmpcds:TfwClientDataset; begin Result:=F ...

  8. vue中如何编写可复用的组件?

    原文地址 Vue.js 是一套构建用户界面的渐进式框架.我们可以使用简单的 API 来实现响应式的数据绑定和组合的视图组件. 从维护视图到维护数据,Vue.js 让我们快速地开发应用.但随着业务代码日 ...

  9. eNSP路由器输出 '#' 无法启动的一种解决方法

    试过网上的改virtulboxIP.关防火墙.改兼容性等方法,都不成功.后来发现通过改变选择路由器的型号可以启动. 如果对路由器没有特殊需求,可以选择型号数字较小的试一下(最低可以选择Router).

  10. 【HANA系列】对话SAP全球CEO孟鼎铭:未来最大的发展机遇属于中国中小企业

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]对话SAP全球CEO孟鼎铭:未来 ...