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 ...
随机推荐
- go xpath
package main import ( "fmt" "github.com/antchfx/htmlquery" "net/http" ...
- spring boot:使用async异步线程池发送注册邮件(spring boot 2.3.1)
一,为什么要使用async异步线程池? 1,在生产环境中,有一些需要延时处理的业务场景: 例如:发送电子邮件, 给手机发短信验证码 大数据量的查询统计 远程抓取数据等 这些场景占用时间较长,而用户又没 ...
- centos8平台使用rz/sz上传下载文件
一,rz/sz的用途 1,rz,sz是Linux/Unix服务器同客户端通过ZModem进行文件传输的命令行工具 说明:客户端需要使用支持ZModem的telnet/ssh客户端(比如windows平 ...
- 服务器同一个tomcat部署2两个相同的项目
项目A,B(B 是A 的复制) 若把A,B工程同时部署到tomcat下,会发生只能访问A,B工程中的其中一个,而另一个会出现404错误(或者无法访问),此时可参照如下方法解决: 步骤1:找到工程下的w ...
- 解决Mac下AndroidStudio内容时卡顿
Mac下AndroidStudio在写代码的时候出现卡顿,小圆圈会一直转,此时我们应该检查下AndroidStudio的内存使用情况了. 1.点击左上角 AndroidStudio -- Prefer ...
- 关于Python的面相对象编程
Python 其实不是面向对象的语言,更像是C语言的面向过程编程的语言 但 Python 也支持 class 关键字来实现类的声明与创建 但 Python 的对象更像是 JavaScript 的函数 ...
- router-view组件在app.vue中渲染不出来怎么办
1.在app.vue使用router-view组件直接渲染 页面什么都没显示,可能问题出在路由配置上了,检查路由是否配置完好,路由挂载那里必须使用routes属性 2.在app.vue中router- ...
- 常用数据结构-集合(set)
集合(set)是python中最容易被忽视的.使用集合的主要好处在于速度快. 集合的一些特性: 集合元素不能重复 不支持索引访问集合中的元素 集合使用散列之后,可以在O(1)时间内访问元素 支持一些常 ...
- C#中的release和debug模式
以下内容来源:https://www.cnblogs.com/rgjycs/p/9254332.html 在程序调试时的debug和release 网上有如下的描述:Debug 通常称为调试版本,它包 ...
- iptables基础原理和使用简介
概念简介 名称 Netfilter/iptables模块有两部分组成: Netfilter框架以及iptables,iptables又分为iptables(内核空间)和iptables命令行工具(用户 ...