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 ...
随机推荐
- 为什么说 Python 内置函数并不是万能的?
本文出自"Python为什么"系列,请查看全部文章 在Python猫的上一篇文章中,我们对比了两种创建列表的方法,即字面量用法 [] 与内置类型用法 list(),进而分析出它们在 ...
- composer慢 设置阿里云镜像
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer
- mongodb安装及使用
安装命令: sudo apt-get install mongodb 开始认证,创建用户: 编辑配置文件: sudo vim /etc/mongodb.conf 11行中的 bind_ip值 修改成为 ...
- 【Azure云服务 Cloud Service】如何在部署云服务Cloud Service时候通过启动任务Start Task来配置IIS (如开启ARR)
问题情形 通过VS部署Cloud Service时,需要在开始任务时候安装或配置其他任务,如安装及配置ARR. 执行步骤 1) 下载 requestRouter_amd64.msi 和 webfarm ...
- 抽空学学KVM(七):虚拟机快照和克隆
前几天学写了KVM中qume-info命令的使用,今天学学在虚拟化里面用处广泛的快照和克隆功能,snapshot和virt-clone.对于snapshot命令的使用其实很简单.进入virsh界面以后 ...
- python文件命名时的注意点
在python中读取Excal文件,需要引用xlrd模块,因此建的这个python文件名为xlrd.py 部分代码如下: import xlrd import os newpath = os.chdi ...
- java关键字之abstract
Java 允许类,借口或成员方法具有抽象属性. abstract 修饰的类叫做抽象类,该类不能被实例化. abstract 修饰的方法叫抽象方法,抽象方法只有声明部分,没有具体的方法体. 接口总是 ...
- Djano之数据库--ORM
一.建立数据库模型类 1.在model里创建模型类.(继承models.Model) 1 class Order(models.Model): 2 TYPE_CHOICE = ( 3 (0, u&qu ...
- python创建Django项目
创建Django项目 关注公众号"轻松学编程"了解更多. 创建一个HelloDjango项目 GitHub地址:https://github.com/liangdongchang/ ...
- 微信小程序——【百景游戏小攻略】
微信小程序--[百景游戏小攻略] 本次课程小项目中的图片以及文章还未获得授权!请勿商用!未经授权,请勿转载! 博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE ...