割点与桥

在一个无向连通图中,若将某个点及其相连的边删除后,图就不连通了,则这样的点被称为割点。

在一个无向连通图中,若将某条边删除后,图就不连通了,则这样的边被称为割边,即桥。

在一张图中求出割点或割边前,我们还需要两个辅助值来得到答案。

时间戳(dfn)

在图的dfs过程中,每个点被第一次访问的时间排行即为时间戳。

追溯值(low)

对于每一个点,该点的追溯值为以该点为根的子树中所有能通过一条不在搜索树上的边能到达该点的点的时间戳最小值。

即对于每一个点\(x\),它的追溯值要满足三个条件:

1)是\(x\)子树中的某点的时间戳;

2)是通过一条不在搜索树上的边能回到\(x\)或其祖先的点的时间戳;

3)满足以上条件的最小值。

那么如何来求\(low[x]\)呢?

首先要使\(low[x]=dfn[x]\),考虑\(x\)的每条连向子节点的边\((x,y)\).

\(low[x]=min(low[x],low[y])\)

若\((x,y)\)不是搜索树上的边,则\(low[x]=min(low[x],dfn[y])\)

代码实现:

void tarjan(int x, int intree) {
dfn[x] = low[x] = ++ cnt;
for (int i = Link[x]; i; i = e[i].next) {
int y = e[i].to;
if (!tarjan[y]) {
tarjan(y, i);
low[x] = min(low[x], low[y]);
}
else if (i != (intree ^ 1)) low[x] = min(low[x], dfn[y]);
}
}
//以下内容在main函数中:
tot = 1;
for (int i = 1; i <= n; ++ i) if (!dfn[i]) tarjan(i);

在这份代码中,为了方便记录某点到子节点的边编号,要将\(tot\)的初值赋为\(1\);以及异或(^)的优先级没有!=高,所以要在\(intree^1\)上加括号提高优先级

得到这些值,我们就可以用来判断某点/边是否为割点/边

割边的判定法则

考虑一条边\((x,y)\),\(y\)是\(x\)的子节点,若\(low[y]<dfn[x]\),即在\(x\)的子树中,没有任何一个点能不通过\((x,y)\)到\(x\)及其祖先上,则说明这条边是割边。

HLOJ的模板题为例:

#include<bits/stdc++.h>
using namespace std; const int N = 100009, M = 300009;
int n, m, Link[N], tot = 1, dfn[N], low[N], cnt;
struct edge{int next, to, bridge;} e[M << 1];
struct answer{int x, y;} ans[M]; inline void add(int x, int y) {e[++ tot].next = Link[x]; Link[x] = tot; e[tot].to = y;} void tarjan(int x, int intree) {
dfn[x] = low[x] = ++ cnt;
for (int i = Link[x]; i; i = e[i].next) {
int y = e[i].to;
if (!dfn[y]) {
tarjan(y, i);
low[x] = min(low[x], low[y]);
if (low[y] > dfn[x]) e[i].bridge = e[i ^ 1].bridge = 1;
}
else if (i != (intree ^ 1)) low[x] = min(low[x], dfn[y]);
}
} inline bool cmp(answer x, answer y) {return x.x == y.x ? x.y < y.y : x.x < y.x;} int main() {
freopen("danger.in", "r", stdin);
freopen("danger.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; ++ i) {
int x, y;
scanf("%d%d", &x, &y);
add(x, y), add(y, x);
}
for (int i = 1; i <= n; ++ i) if (!dfn[i]) tarjan(i, 0);
cnt = 0;
for (int i = 2; i < tot; i += 2) if (e[i].bridge) ans[++ cnt].x = min(e[i ^ 1].to, e[i].to), ans[cnt].y = max(e[i ^ 1].to, e[i].to);
sort(ans + 1, ans + cnt + 1, cmp);
for (int i = 1; i <= cnt; ++ i) printf("%d %d\n", ans[i].x, ans[i].y);
return 0;
}

由于上文提到\(tot\)从\(1\)开始,所以在得出割边是要从tot=2开始枚举。

割点的判定法则

类似于判定割边,只要满足\(low[y]<=dfn[x]\)的点即为割点。

求割点的方法类似,故不再赘述。

两道例题

BZOJ1123 BLO

题意

给出一张无向连通图,求去掉每一个点后有多少有序点对不连通

\((n<=100000,m<=500000)\)

题解

若某一个点不是割点,即删除该点后图仍然连通,则只有该点产生\(2(n-1)\)的贡献;

考虑某一点\(x\)是割点,删除它后我们把图分成三部分考虑:

1)\(x\)本身

2)\(x\)子树内除了\(x\)的点

3)\(x\)子树外的点

这三者的大小分别为\(1\),\(size[y]\),\(n-1-\sum size[y]\).

那么答案为\(\sum size[y]*(n-size[y])+(n-1)+(\sum size[y])*(n-1-\sum size[y])\)

有关图的连通性的Tarjan算法的更多相关文章

  1. 求图的强连通分量--tarjan算法

    一:tarjan算法详解 ◦思想: ◦ ◦做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间 ...

  2. 萌新学习图的强连通(Tarjan算法)笔记

    --主要摘自北京大学暑期课<ACM/ICPC竞赛训练> 在有向图G中,如果任意两个不同顶点相互可达,则称该有向图是强连通的: 有向图G的极大强连通子图称为G的强连通分支: Tarjan算法 ...

  3. Tarjan算法与割点割边

    目录 Tarjan算法与无向图的连通性 1:基础概念 2:Tarjan判断割点 3:Tarjan判断割边 Tarjan算法与无向图的连通性 1:基础概念 在说Tarjan算法求解无向图的连通性之前,先 ...

  4. 图的连通性——Tarjan算法&割边&割点

    tarjan算法 原理: 我们考虑 DFS 搜索树与强连通分量之间的关系. 如果结点 是某个强连通分量在搜索树中遇到的第⼀个结点,那么这个强连通分量的其余结点肯定 是在搜索树中以 为根的⼦树中. 被称 ...

  5. 图的连通性--Tarjan算法

    一些概念 无向图: 连通图:在无向图中,任意两点都直接或间接连通,则称该图为连通图.(或者说:任意两点之间都存在可到达的路径) 连通分量: G的 最大连通子图 称为G的连通分量. 有向图 (ps.区别 ...

  6. Tarjan算法:求解图的割点与桥(割边)

    简介: 割边和割点的定义仅限于无向图中.我们可以通过定义以蛮力方式求解出无向图的所有割点和割边,但这样的求解方式效率低.Tarjan提出了一种快速求解的方式,通过一次DFS就求解出图中所有的割点和割边 ...

  7. 关于连通性问题的Tarjan算法暂结

    关于基础知识的预备桥和割点.双联通分量.强连通分量,支配树.(并不会支配树) 关于有向图的Tarjan,是在熟悉不过的了,它的主要功能就是求强联通分量,缩个点,但是要注意一下构建新图的时候有可能出现重 ...

  8. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...

  9. 【强联通图 | 强联通分量】HDU 1269 迷宫城堡 【Kosaraju或Tarjan算法】

      为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明 ...

随机推荐

  1. Spring Security使用数据库数据完成认证--练气后期2

    写在前面 没错,这篇文章还是练气后期!但作者我相信筑基指日可待! 在前一篇文章当中,我们简单地分析了一下Spring Security的认证流程,知道了如果想要实现对自己用户数据(账户.角色.权限)的 ...

  2. python - 平方根格式化 + 字符串分段组合

    题目来源:python123 平方根格式化 描述 获得用户输入的一个整数a,计算a的平方根,保留小数点后3位,并打印输出.‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪ ...

  3. RPC的入门应用

    一.什么是RPC RPC 的全称是 Remote Procedure Call ,是一种进程间通信方式.它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这 ...

  4. 删除MBR分区如何使用光盘恢复

    1.备份MBR分区表 dd  if=/dev/sda  of=/data/mbr.bak  bs=1  count=64  skip=446 分区表前512字节分为三部分,第一部分446字节与启动相关 ...

  5. unity5打包机制下,一种资源打ab和资源管理的方案

    unity5打包机制下,一种资源打ab和资源管理的方案.1.打ab: 1.设置平台 2.清楚所有资源的assetbundlename: string[] abNameArr = AssetDataba ...

  6. 【转】Android 5.0 : Parsing Data for android-21 failed unsupported major.minor version 51.0

    http://code2care.org/pages/parsing-data-for-android-21-failed-unsupported-major.minor-version-51.0/ ...

  7. 熟练剖分(tree) 树形DP

    熟练剖分(tree) 树形DP 题目描述 题目传送门 分析 我们设\(f[i][j]\)为以\(i\)为根节点的子树中最坏时间复杂度小于等于\(j\)的概率 设\(g[i][j]\)为当前扫到的以\( ...

  8. 基于django快速开发一个网站(一)

    基于django快速开发一个网站(一) *  创建虚拟环境.基于虚拟环境创建django==2.0.0和图片加载库和mysql数据库驱动 1. 创建目录并创建虚拟环境 ╰$ mkdir Cornuco ...

  9. HTTPS建立过程

    由于HTTPS建立过程经常忘记,固记录 HTTPS建立流程 客户端发起SSL连接 服务端发送证书(证书中包含了服务端公钥) 客户端根据已有证书判断是否是可信任的(客户端决定是否继续) 服务端要求客户端 ...

  10. leetcode刷题-43字符串相乘

    题目 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 思路 字符串转数字:从字符串第一位开始取,每次取出的值转换为数字 ...