Tarjan算法求割点
(声明:以下图片来源于网络)
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(该集合中最早遍历到的点的时间戳)
观察上图,可以发现割点求法可以分成两种情况讨论。
- 若该点为根节点,若有该节点拥有两个及以上互不相连的子树,则删除该点会得到这些子树。所以该点为割点。
(now == root && child >= 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算法求割点的更多相关文章
- Tarjan 算法求割点、 割边、 强联通分量
Tarjan算法是一个基于dfs的搜索算法, 可以在O(N+M)的复杂度内求出图的割点.割边和强联通分量等信息. https://www.cnblogs.com/shadowland/p/587225 ...
- tarjan算法求割点cojs 8
tarjan求割点:cojs 8. 备用交换机 ★★ 输入文件:gd.in 输出文件:gd.out 简单对比时间限制:1 s 内存限制:128 MB [问题描述] n个城市之间有通讯网 ...
- [学习笔记] Tarjan算法求桥和割点
在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥.割点,也是和上篇有博客有类似之处的. 关于桥和割点: 桥:在一个有向图中,如果删去一条边,而 ...
- ZOJ Problem - 2588 Burning Bridges tarjan算法求割边
题意:求无向图的割边. 思路:tarjan算法求割边,访问到一个点,如果这个点的low值比它的dfn值大,它就是割边,直接ans++(之所以可以直接ans++,是因为他与割点不同,每条边只访问了一遍) ...
- [Tarjan系列] Tarjan算法求无向图的双连通分量
这篇介绍如何用Tarjan算法求Double Connected Component,即双连通分量. 双联通分量包括点双连通分量v-DCC和边连通分量e-DCC. 若一张无向连通图不存在割点,则称它为 ...
- HDU 1269 迷宫城堡 tarjan算法求强连通分量
基础模板题,应用tarjan算法求有向图的强连通分量,tarjan在此处的实现方法为:使用栈储存已经访问过的点,当访问的点离开dfs的时候,判断这个点的low值是否等于它的出生日期dfn值,如果相等, ...
- POJ 1986 Distance Queries (Tarjan算法求最近公共祖先)
题目链接 Description Farmer John's cows refused to run in his marathon since he chose a path much too lo ...
- tarjan算法求LCA
tarjan算法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 这里我们使用tarjan算法离线算法解决这个问题. 离线 ...
- Tarjan算法求有向图强连通分量并缩点
// Tarjan算法求有向图强连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> #inc ...
随机推荐
- logstash -grok插件语法介绍
介绍 logstash拥有丰富的filter插件,它们扩展了进入过滤器的原始数据,进行复杂的逻辑处理,甚至可以无中生有的添加新的 logstash 事件到后续的流程中去!Grok 是 Logsta ...
- is, ==, id 用法、代码块和缓存机制
id(): 获取对象的内存地址:print(id(i)) == : 比较两边的值是否相同 is : 判断内存地址是否相同 id相同,值一定相同 值相同,id不一定相同 代码块: Python是由代码块 ...
- py正则表达式(全是干货系列)
正则表达式的作用在这里不多赘述了,反正处理文本任务贼六就对了.Python中的正则表达式是内置在re模块中的,我们就对这个模块进行详细地讲解.这是一篇媲美帮助文档的文章!对就这么自信,不服你顺着网 ...
- C++类模板声明与定义为何不能分开
我们用C++写类的时候,通常会将.cpp和.h文件分开写,即实现和声明分开写了:但在C++的类模板中,这种写法是错误的. 在<C++编程思想>的第16章的"16.3模板语法&qu ...
- find for /f 分割字符串 bat
@Echo off::总用例数For /f "tokens=2" %%i in ('Type bat.txt^|Find "Ran"') do (Echo %% ...
- pyside2安装避坑
cmd 输入 pip install PySide2 官方下载太慢 清华源: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pysid ...
- 论文解读《Plug-and-Play Priors for Model Based Reconstruction》
这篇论文主要概述了model-baesd的方法在解决图像恢复的逆问题的很好的效果,降噪问题其实就是前向模型的H是一个恒等算子,将state-of-the-art的降噪算法(先验模型)和相对应的逆问题的 ...
- vue-cli3使用jq
第一步安装 npm install jquery --save 第二部配置vue.config.js, 没有这个文件就创建 主要是框框出来的那些: 忽略我配置的另一个uglifyjs-webpack- ...
- Java学习的第十天
1.类方法 实例方法 自定义方法 2.今天使用visio不太会使用,方法覆盖不懂. 3.明天将方法剩余部分学完
- MONGODB01 - Prematurely reached end of stream 错误定位及修复
最近项目在运行过程,当一段时间没有操作mongo,再次访问报错,如下 org.springframework.data.mongodb.UncategorizedMongoDbException: P ...