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 ...
随机推荐
- centos8:linux平台查看线程(ps/pstree/top)
一,ps/pstree/top命令所属的rpm包 pstree所属的包 [root@blog ~]# whereis pstree pstree: /usr/bin/pstree /usr/bin/p ...
- mysql中事件失效如何解决
重启Mysql服务可能会导致event_scheduler关闭,事件失效.解决方法如下: 1.解决办法: #查看是否开启 show variables like 'event_scheduler'; ...
- 第十六章 IP子网的划分
一.引入 1.根据IP地址的类别进行IP地址分配的方法表现出越来越多的弊端 2.为了解决分类IP地址划分带来的地址浪费,就需要使用子网划分(Subnetting)的方法 3.VLSM和CIDR可以进一 ...
- jinjia2语言
金家兔 网站: https://jinja.palletsprojects.com/en/2.11.x/ #Jinja is Beautiful {% extends "layout.htm ...
- date命令之移动修改日志日期
[16:19:50 root@C8[ 2020-06-16DIR]#touch app.log [16:21:25 root@C8[ 2020-06-16DIR]#ll total 0 -rw-r-- ...
- 国产化即时通信系统开发 -- 实现GGTalk的登录界面(Linux、Ubuntu、UOS、中标麒麟)
距离2013年开源GGTalk以来,7年已经过去了,GGTalk现在有了完整的PC版.安卓版.iOS版(即将发布),以及Xamarin版本. 然而,时代一直在变化,在今天,有个趋势越来越明显,那就是政 ...
- poj1011 Sticks (搜索经典好题)
poj1011 Sticks 题目连接: poj1011 Description George took sticks of the same length and cut them randomly ...
- Java安全之Commons Collections2分析
Java安全之Commons Collections2分析 首发:Java安全之Commons Collections2分析 0x00 前言 前面分析了CC1的利用链,但是发现在CC1的利用链中是有版 ...
- 第1天|12天搞定Python网络爬虫,吃里爬外?
人力资源部漂亮的小MM,跑来问我:老陈,数据分析和爬虫究竟是关系呀?说实在的,我真不想理她,因为我一直认为这个跟她的工作关系不大,可一想到她负责我负责部门的招聘工作,我只好勉为其难地跟她说:数据分析, ...
- 浅谈DevOps
DevOps: Development和Operations的组合,是一种软件开发方法,涉及软件在整个开发生命周期中的持续开发,持续测试,持续集成,持续部署和持续监控. 可以把DevOps看作系统开发 ...