(声明:以下图片来源于网络)

Tarjan算法求出割点个数

首先来了解什么是连通图

在图论中,连通图基于连通的概念。在一个无向图 G 中,若从顶点i到顶点j有路径相连(当然从j到i也一定有路径),则称i和j是连通的。如果 G 是有向图,那么连接i和j的路径中所有的边都必须同向。如果图中任意两点都是连通的,那么图被称作连通图。如果此图是有向图,则称为强连通图(注意:需要双向都有路径)。图的连通性是图的基本性质。

——摘自度娘

通俗易懂,不在解释。

举个例子吧:



如上图,各个节点皆可以到达任意节点,所以该图为连通图。

再来了解什么是割点

在一个无向图中,如果有一个顶点集合,删除这个顶点集合以及这个集合中所有顶点相关联的边以后,图的连通分量增多,就称这个点集为割点集合。

如果某个割点集合只含有一个顶点X(也即{X}是一个割点集合),那么X称为一个割点。

——摘自度娘

了解完定义之后,不难通过定义来求出图的割点——暴力DFS。

即是:从1到n遍历每一个点,每次遍历到这个点时,只需要删除该点,判断删除后是否会增加联通量即可。

这种方法时间复杂度最坏为\(O(n×(n+m))\),只要数据大一点就会被卡爆,这里不详细叙述。

使用Tarjan算法求割点

可以参考本人的Tarjan算法缩点博客

依然定义:dfn(时间戳),low(该集合中最早遍历到的点的时间戳)

观察上图,可以发现割点求法可以分成两种情况讨论。

  1. 若该点为根节点,若有该节点拥有两个及以上互不相连的子树,则删除该点会得到这些子树。所以该点为割点。

    now == root && child >= 2
  2. 若该点不为根节点,若不存在可以在DFS中可以遇到已访问节点的连边时(通俗的说,就是不可以找到回去的路),则该点为割点。

    now != root && low[next] >= dfn[now]

low的值可以证明发现:

low的初始值为该节点的时间戳。

即是:low[now]=dfn[now]

若当前结点 now 的所连结点 next 正在被访问,则 low[now]=min(low[now],dfn[next])

若当前结点 now 的所连结点 next 未被访问,则

low[now]=min(low[now],low[next])

C++代码实现:

void Tarjan(int now, int father, int root) {
dfn[now] = low[now] = ++tim;
int child = 0; //若now为根节点时子树的个数
int SIZ = v[now].size();
for(int i = 0; i < SIZ; i++) {
int next = v[now][i];
if(!dfn[next]) {
if(now == root) {
child++;
}
Tarjan(next, now, root);
low[now] = min(low[now], low[next]);
if(now == root && child >= 2)//处理情况一
cut[now] = true;
else if(now != root && low[next] >= dfn[now])//处理情况二
cut[now] = true;
}
if(next != father)
low[now] = min(low[now], dfn[next]);//更新low值
}
}
void Build() {
for(int i = 1; i <= n; i++)
if(!dfn[i])
Tarjan(i, i, i);
}

附上一道板题

题目背景

割点

题目描述

给出一个\(n\)个点,\(m\)条边的无向图,求图的割点。

输入格式

第一行输入两个正整数\(n,m\)。

下面\(m\)行每行输入两个正整数\(x,y\)表示\(x\)到\(y\)有一条边。

输出格式

第一行输出割点个数。

第二行按照节点编号从小到大输出节点,用空格隔开。

输入输出样例

输入

6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6

输出

1
5

思路

板题,套上即可。

C++代码:

#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 2e4 + 5;
vector<int> v[MAXN];
int dfn[MAXN], low[MAXN];
bool cut[MAXN];
int tim, cnt;
int n, m;
void Read();
void Build();
void Tarjan(int, int, int);
int main() {
Read();
Build();
return 0;
}
void Build() {
for(int i = 1; i <= n; i++)
if(!dfn[i])
Tarjan(i, i, i);
for(int i = 1; i <= n; i++)
if(cut[i])
cnt++;
printf("%d\n", cnt);
for(int i = 1; i <= n; i++)
if(cut[i])
printf("%d ", i);
}
void Tarjan(int now, int father, int root) {
dfn[now] = low[now] = ++tim;
int child = 0;
int SIZ = v[now].size();
for(int i = 0; i < SIZ; i++) {
int next = v[now][i];
if(!dfn[next]) {
if(now == root) {
child++;
}
Tarjan(next, now, root);
low[now] = min(low[now], low[next]);
if(now == root && child >= 2)
cut[now] = true;
else if(now != root && low[next] >= dfn[now])
cut[now] = true;
}
if(next != father)
low[now] = min(low[now], dfn[next]);
}
}
void Read() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
int A, B;
scanf("%d %d", &A, &B);
v[A].push_back(B);
v[B].push_back(A);
}
}

Tarjan算法求割点的更多相关文章

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

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

  2. tarjan算法求割点cojs 8

    tarjan求割点:cojs 8. 备用交换机 ★★   输入文件:gd.in   输出文件:gd.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] n个城市之间有通讯网 ...

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

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

  4. ZOJ Problem - 2588 Burning Bridges tarjan算法求割边

    题意:求无向图的割边. 思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍) ...

  5. [Tarjan系列] Tarjan算法求无向图的双连通分量

    这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...

  6. HDU 1269 迷宫城堡 tarjan算法求强连通分量

    基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...

  7. POJ 1986 Distance Queries (Tarjan算法求最近公共祖先)

    题目链接 Description Farmer John's cows refused to run in his marathon since he chose a path much too lo ...

  8. tarjan算法求LCA

    tarjan算法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 这里我们使用tarjan算法离线算法解决这个问题. 离线 ...

  9. Tarjan算法求有向图强连通分量并缩点

    // Tarjan算法求有向图强连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> #inc ...

随机推荐

  1. centos8上安装ImageMagick6.9.10并压缩图片生成webp缩略图

    一,ImageMagick的作用: ImageMagick 是一个用来创建.编辑.合成图片的软件. 它可以读取.转换.写入多种格式的图片. 功能包括:图片切割.颜色替换.各种效果的应用, 图片的旋转. ...

  2. 【线上排查实战】AOP切面执行顺序你真的了解吗

    前言 忙,是我这个月的主旋律,也是我频繁鸽文章的接口----蛮三刀把刀 公司这两个月启动了全新的项目,项目排期满满当当,不过该学习还是要学习.这不,给公司搭项目的时候,踩到了一个Spring AOP的 ...

  3. 503. 下一个更大元素 II

    503. 下一个更大元素 II 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大 ...

  4. 使用Vue简单的写组件的UI库

    初始化项目vue create nature-ui 在根目录下面创建一个文件目录放置组件(我这里的创建packages) packages 目录下面创建个个组件的名称并创建index.js(用于输出所 ...

  5. js中!!的运用

    最近在看vue源码. 里面使用Object.defineProperty()中!!吸引眼球 1 export function def (obj: Object, key: string, val: ...

  6. D. Generating Sets 解析(思維)

    Codeforce 722 D. Generating Sets 解析(思維) 今天我們來看看CF722D 題目連結 題目 略,請直接看原題 前言 真的是沒想到... @copyright petje ...

  7. exe打包成安装文件(界面美观)

    前言 在开发windows桌面应用过程中,软件交付时,一般都是交付安装包. 安装文件的优点 显得更正规,安装界面也可展示软件特点介绍,可自动生成桌面图标等: 安装包体积要比软件小,方便下载. 探索之路 ...

  8. 浅谈分布式共识算法raft

    前言:在分布式的系统中,存在很多的节点,节点之间如何进行协作运行.高效流转.主节点挂了怎么办.如何选主.各节点之间如何保持一致,这都是不可不面对的问题,此时raft算法应运而生,专门 用来解决上述问题 ...

  9. 嵌入式linux和stm32嵌入式开发这两者之间有什么关联性

    对于更开始入坑的同学,可能也像我一样搞不清楚两者的区别与联系.现在结合知乎网上的相关资料发一篇文章来具体分析. 基于STM32的开发属于微控制器开发领域,主要开发工具是keil或IAR,这种开发更准确 ...

  10. ArrayList扩容机制

    一.先从 ArrayList 的构造函数说起 ArrayList有三种方式来初始化,构造方法源码如下: 1 /** 2 * 默认初始容量大小 3 */ 4 private static final i ...