这是DFS系列的第二篇

割边的概念

In graph theory, a bridgeisthmuscut-edge, or cut arc is an edge of a graph whose deletion increases its number of connected components. Equivalently, an edge is a bridge if and only if it is not contained in any cycle. A graph is said to be bridgeless or isthmus-free if it contains no bridges.

Let $G = (V, E)$ be a connected, undirected graph, a bridge of $G$ is an edge whose removal disconnects $G$. (Introduction to Algorithms p.621)

注意割边这一概念只适用于无向图,不适用于有向图,因为有向图的连通性和无向图的连通性是完全不同的两个概念。对于某有向图 $G$,简单地称它连通是很不完善的。有向图的连通性有强连通(strongly connected)和半连通(semiconnected)两种常见的提法。上面英文描述中的“graph”及下文中的“”均指无向图

割边 (cut edge)也称作(bridge)是删除后能使图的连通分量增加的边。

下面我们只考虑没有重边的无向图

考虑一个连通的无向图 $G$,若它含有某条割边 $(u, v)$,那么去掉这条边后,将得到2个连通图 $G'$,$H'$,而不可能得到 $2$ 个以上连通图,因为一条边最多能将 $2$ 个连通图合为一个联通图。(这句话貌似和上下文无关)

下面介绍求无向图所有割边的Tarjan算法(Tarjan's Bridge-Finding Algorithm

我们只考虑对无向连通图 $G$ 求割边,若图 $G$ 不连通那么就对 $G$ 的各个连通分量求割边。

我们知道 DFS 一个无向图将其所有边分成两类树边(tree edge)与回边(back edge)。显然地,割边只能是树边而绝不可能是回边。

考虑 一条树边 $(u\to v)$ 是割边 的条件。这条件应当是在DFS树中,以 $v$ 为根的子树(简称子树 $v$)中的所有节点都没有连向 $u$ 的祖先节点(包括 $u$ 本身)的回边,也就是说子树 $v$ 仅仅靠着边 $(u,v)$ 和其他节点保持连通。

为了判断上述条件,我们在 DFS 过程中记录每个节点的 dfn 值与 low 值,树边 $(u\to v)$ 是割边的充要条件即是 \(\color{blue}{\mathrm{low}[v]>\mathrm{dfn}[u]}\) 。

struct edge{
int to, nt;
bool flag;
}E[MAX_E<<];
int head[MAX_V]; int dfn[MAX_V], low[MAX_V];
int ts; //time stamp
void dfs(int u, int f){
dfs[u]=low[u]=++ts;
for(int i=head[i]; ~i; i=E[i].nt){
int &v=E[i].to;
if(!dfn[v]){ //tree edge
dfs(v, f);
low[u]=min(low[u], low[v]);
if(low[v]>dfn[u]){
e[i].flag=e[i^].flag=true;
}
}
else if(v!=f&&dfn[v]<dfn[u]){ //back edge
low[u]=min(low[u], dfn[v]);
}
}
} void solve(int N){
memset(dfn, , sizeof(dfn));
ts=;
for(int i=; i<=N; i++)
if(!dfn[i]) dfs(i, i);
}

现在考虑有重边的情况。这时上面的写法不能识别所有回边。首先明确一点:不论是否有重边,DFS 都将所有边分成树边回边两类。

但是按上面的写法,所有重边要么全是树边,要么全是回边,因而不能识别所有回边(这并不是 DFS 算法本身有问题,而是写法有问题)。这是因为 DFS 的参数是 $u$(当前节点)和 $f$(当前节点的父亲节点),我们判断回边的依据是

else if(v!=f&&dfn[v]<dfn[u]){	//back edge
low[u]=min(low[u], dfn[v]);
}

解决办法是将参数 $u$换成树边 $( u\to f )$ 的编号。

struct edge{
int to, nt, id;
bool tag;
}E[MAX_N<<];
int head[MAX_N]; int dfn[MAX_N], low[MAX_N], ts; //time_stamp
void dfs(int u, int te){
dfn[u]=low[u]=++ts;
for(int i=head[u]; ~i; i=E[i].nt){
int &v=E[i].to, &id=E[i].id;
if(!dfn[v]){ //tree_edge
dfs(v, id);
low[u]=min(low[u], low[v]);
if(low[v]>dfn[u])
e[i].tag=true;
}
else if(id!=te&&dfn[v]<dfn[u]){ //back_edge
low[u]=min(low[u], dfn[v]);
}
}
}

一般来说,没必要在结构体 edge 内加个变量 id,按通常的建图方式,无向边的 ID 就是其对应的某条有向边的 ID 右移一位。

连通性2 无向图的割边 (cut edge)的更多相关文章

  1. ZOJ2588 Burning Bridges 无向图的割边

    题目大意:求无向图的割边编号. 割边定义:在一个连通图中,如果删去一个边e,图便变成不连通的两个部分,则e为该图的割边. 求法:边(u,v) 不是割边,当且仅当边(u,v)在一个环内.因此所有不在环内 ...

  2. 图连通性【tarjan点双连通分量、边双联通分量】【无向图】

    根据 李煜东大牛:图连通性若干拓展问题探讨 ppt学习. 有割点不一定有割边,有割边不一定有割点. 理解low[u]的定义很重要. 1.无向图求割点.点双联通分量: 如果对一条边(x,y),如果low ...

  3. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

  4. [HDOJ4738]Caocao's Bridges(双联通分量,割边,tarjan)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738 给一张无向图,每一条边都有权值.找一条割边,使得删掉这条边双连通分量数量增加,求权值最小那条. ...

  5. Tarjan 强连通分量 及 双联通分量(求割点,割边)

    Tarjan 强连通分量 及 双联通分量(求割点,割边) 众所周知,Tarjan的三大算法分别为 (1)         有向图的强联通分量 (2)         无向图的双联通分量(求割点,桥) ...

  6. LCT(link cut tree) 动态树

    模板参考:https://blog.csdn.net/saramanda/article/details/55253627 综合各位大大博客后整理的模板: #include<iostream&g ...

  7. Tarjan 算法求割点、 割边、 强联通分量

    Tarjan算法是一个基于dfs的搜索算法, 可以在O(N+M)的复杂度内求出图的割点.割边和强联通分量等信息. https://www.cnblogs.com/shadowland/p/587225 ...

  8. UVA796- Critical Links(无向图中的桥梁)

    题目链接 题意: 给出一个无向图,按顺序输出桥 思路:求出全部的桥,然后按顺序输出就可以 代码: #include <iostream> #include <cstdio> # ...

  9. UVA315- Network(无向图割点)

    题目链接 题意: 给出一张无向图,求割点的个数 思路:非常裸的题目.直接套用模版就可以. 代码: #include <iostream> #include <cstdio> # ...

随机推荐

  1. Android 动态加载 (一) 态加载机制 案例一

    在目前的软硬件环境下,Native App与Web App在用户体验上有着明显的优势,但在实际项目中有些会因为业务的频繁变更而频繁的升级客户端,造成较差的用户体验,而这也恰恰是Web App的优势.本 ...

  2. Sublime Text2 安装Package Control

    Sublime Text2是一款轻量级的妖娆的编辑器,想要更多私人定制功能的第一步就是安装Package  Control 这是官网的安装方法: Click the Preferences >  ...

  3. KVM虚拟机CPU说明

    废话不多说了,下面对kvm虚拟机的CPU说明做一梳理:NUMA技术介绍NUMA是一种解决多CPU共同工作的技术方案,我们先回顾下多CPU共同工作的技术架构历史.多CPU共同工作主要有三种架构,分别是S ...

  4. yepnope初体验

    真是一个百花齐放的项目,在熟悉代码的过程中,看到各种前端.后端技术,这回又冒出一个yepnope的东东,搜索了一下,不是什么新技术,打开官方网站,已经弃用的通知非常醒目,但仍提供相关文档在github ...

  5. C#属性: 利用set实现递归

    直接帖代码: public class Bird { int xdata; /// <summary> /// 属性的简洁写法,等同于下面的xData方式 /// </summary ...

  6. [iOS翻译]Cocoa编码规范

        简介: 本文整理自Apple文档<Coding Guidelines for Cocoa>.这份文档原意是给Cocoa框架.插件及公共API开发者提供一些编码指导,实质上相当于Ap ...

  7. Android 获取地理位置的经度和纬度(zz)

    在Android应用程序中,可以使用LocationManager来获取移动设备所在的地理位置信息.看如下实例:新建android应用程序TestLocation. 1.activity_main.x ...

  8. iOS中plist的创建,数据写入与读取

    iOS中plist的创建,数据写入与读取 Documents:应用将数据存储在Documents中,但基于NSuserDefaults的首选项设置除外Library:基于NSUserDefaults的 ...

  9. VS2010下配置使用OpenGL的glut库

    我已在我机上测试成功,机装VS2010! 在win7(windows7 ultimate SP1)下成功安装VS2010(Visual Studio 2010 ultimate x86). 下载glu ...

  10. 学习笔记——Maven实战(八)常用Maven插件介绍(下)

    我们都知道Maven本质上是一个插件框架,它的核心并不执行任何具体的构建任务,所有这些任务都交给插件来完成,例如编译源代码是由maven- compiler-plugin完成的.进一步说,每个任务对应 ...