tarjan 复习笔记 割点与桥
定义分析
给定一个无向连通图\(G=(V,E)\)
对于\(x\in Y\),如果删去\(x\)及与\(x\)相连的边后,\(G\)分裂为两个或者两个以上的不连通子图,那么称\(x\)为\(G\)的割点
对于\((x,y)\in E\),如果删去\((x,y)\)后,\(G\)分裂为两个不连通的子图,那么就称\((x,y)\)为\(G\)的桥或者割边
一般无向图(不保证连通)的割点和桥 指的是各个连通块的割点和桥

在这个图中,\(1,6\)号结点为割点,\((1,6),(6,7)\)是桥
概念引入(Tarjan独特概念)
时间戳:对一张无向连通图进行DFS,使每个点只经过一遍,并且按照每个点第一次被访问的时间顺序依次标号(也就是他们的DFS序),这个标号被称为时间戳,记为\(dfs_x\).
搜索树:在时间戳形成的DFS过程中,我们发现所有构成递归的边构成了一棵树,称之为无向连通图的搜索树.
追溯值:设\(subtree(x)\)表示搜索树中以\(x\)为根的子树,节点\(u\)的追溯值我们定义为\(low_u\),定义为一下结点时间戳的最小值.
1、位于\(subtree(x)\)中的节点.
2、通过一条不在搜索树上的边,可以到达\(subtree(x)\)的节点.
构建方法(追溯值,时间戳)

第一次访问到一个节点\(x\)的时候,首先我们令\(low_x=dfn_x\).
然后,我们继续考虑与\(x\)相邻的每一条边,如果没有被访问过,那么就递归
地却访问他们,回溯是更新\(low_x\).如果\(y\in subtree(x)\),那么\(low_x=min(low_x,low_y)\).
否则\(low_x=min(low_x,dfn_y)\).
割点的判定
- 如果\(x\)不是搜索树上的根节点,那么\(x\)的割点判定条件为当且仅当搜索树上的一个子节点\(y\)满足
\]
解释:(请先理解好追溯值定义)这个公式表示的意思是在\(subtree(y)\)中的点如果不经过\(x\)那么就无法到达比\(x\)更早访问过的点。
特殊情况:如果\(x是根节点\),那么\(x\)是割点当且仅当搜索树上的两个子节点\(y\)满足上述条件时成立,表示这两个子节点无法互相到达
桥的判定
- 无向边\((x,y)\)是桥,当且仅当\((x,y)\),位于搜索树上,并且在搜索树上\(x\)的一个子节点\(y\)满足
\]
表示从\(subtree(y)\)出发,在不经过\((x,y)\)的前提下,无论是怎么走都无法到达\(x\)或者比\(x\)更早访问过的节点
当然,一个简单环里面的边一定不是桥,因为他是圈圈!!!
不在搜索树上的边至少都位于至少一个环中,因为不在搜索树上的边那么就表示它一定是连接到了已经被搜索过的点,所以当通过那个点的时候一定能在回到它本身,所以一定在至少一个环中
割点,桥判定代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+9;
struct node{
int last;
int to;
}e[N*2];
int head[N],vis[N],dfn[N],low[N],cut[N],cnt,poi,tot;
int n,m,root;
void add(int from,int to)
{
e[++cnt].last=head[from];
e[cnt].to=to;
head[from]=cnt;
}
void tarjan(int x)
{
dfn[x]=low[x]=++poi;
int flag=0;//根节点的判断
for(int i=head[x];i;i=e[i].last)
{
int v=e[i].to;
if(!dfn[v])//没有打时间戳说明未被搜索到过
{
tarjan(v);
low[x]=min(low[v],low[x]);
if(low[v]>=dfn[x])
{
flag++;
if(x!=root||flag>1)
{
cut[x]=1;
}
}
}
else low[x]=min(low[x],dfn[v]);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
if(x==y) continue;
add(x,y);
add(y,x);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
root=i;
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
if(cut[i]) tot++;
}
cout<<tot<<endl;
for(int i=1;i<=n;i++)
{
if(cut[i]) cout<<i<<" "; //输出割点
}
return 0;
}```
```void tarjan(int x, int in_edge) //求桥
{
dfn[x] = low[x] = ++num;
for (int i = head[x]; i; i = Next[i]) {
int y = ver[i];
if (!dfn[y]) {
tarjan(y, i);
low[x] = min(low[x], low[y]);
if (low[y] > dfn[x])
bridge[i] = bridge[i ^ 1] = true;
}
else if (i != (in_edge ^ 1))
low[x] = min(low[x], dfn[y]);
}
}
tarjan 复习笔记 割点与桥的更多相关文章
- Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂
更好的阅读体验&惊喜&原文链接 感谢@yxc的腿部挂件 大佬,指出本文不够严谨的地方,万分感谢! Tarjan无向图的割点和桥(割边) 导言 在掌握这个算法前,咱们有几个先决条件. [ ...
- tarjan复习笔记
tarjan复习笔记 (关于tarjan读法,优雅一点读塔洋,接地气一点读塔尖) 0. 连通分量 有向图: 强连通分量(SCC)是个啥 就是一张图里面两个点能互相达到,那么这两个点在同一个强连通分量里 ...
- 学习笔记--Tarjan算法之割点与桥
前言 图论中联通性相关问题往往会牵扯到无向图的割点与桥或是下一篇博客会讲的强连通分量,强有力的\(Tarjan\)算法能在\(O(n)\)的时间找到割点与桥 定义 若您是第一次了解\(Tarjan\) ...
- Tarjan求无向图割点、桥详解
tarjan算法--求无向图的割点和桥 一.基本概念 1.桥:是存在于无向图中的这样的一条边,如果去掉这一条边,那么整张无向图会分为两部分,这样的一条边称为桥无向连通图中,如果删除某边后,图变成不 ...
- tarjan复习笔记 双连通分量,强连通分量
声明:图自行参考割点和桥QVQ 双连通分量 如果一个无向连通图\(G=(V,E)\)中不存在割点(相对于这个图),则称它为点双连通图 如果一个无向连通图\(G=(V,E)\)中不存在割边(相对于这个图 ...
- 求无向图的割点和桥模板(tarjan)
一.基本概念 1.桥:若无向连通图的边割集中只有一条边,则称这条边为割边或者桥 (离散书上给出的定义.. 通俗的来说就是无向连通图中的某条边,删除后得到的新图联通分支至少为2(即不连通: 2.割点:若 ...
- 割点和桥---Tarjan算法
使用Tarjan算法求解图的割点和桥. 1.割点 主要的算法结构就是DFS,一个点是割点,当且仅当以下两种情况: (1)该节点是根节点,且有两棵以上的子树; (2)该节 ...
- Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)【转】【修改】
一.基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成 ...
- (转)Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
基本概念: 1.割点:若删掉某点后,原连通图分裂为多个子图,则称该点为割点. 2.割点集合:在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个 ...
随机推荐
- springboot日志输出到文件
今天来谈一谈日志,主要是说一说springboot的日志,因为最近在学习springboot.首先在写代码的时候,要养成记日志的习惯,这点真的很重要,因为之前吃了很多亏.过去我对日志很不在意,该有的日 ...
- spring boot集成mybatis-plus插件进行自定义sql方法开发时报nested exception is org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
spring boot集成mybatis-plus插件进行自定义sql方法开发时报nested exception is org.apache.ibatis.binding.BindingExcept ...
- 第四章节 BJROBOT 线速度校正 【ROS全开源阿克曼转向智能网联无人驾驶车】
BJROBOT 线速度校正 1.把小车平放在地板上,用卷尺作为测量刻度,选取车头或者车尾处作为小车的起点, 打开资料里的虚拟机,打开一个终端 ssh 过去主控端启动 roslaunch znjro ...
- Java中几种常见的循环
多重if_else: package com.dengchaoqun.ht; public class Double_For02 { /** * * 打印乘法表 */ public static vo ...
- pixi.js 自定义光标样式
pixi 介绍 Pixi是一个超快的2D渲染引擎,通过Javascript和Html技术创建动画或管理交互式图像,从而制作游戏或应用. 项目地址:https://github.com/pixijs/p ...
- 查找linux系统下的端口被占用进程的两种方法 【转】
在linux下开发时,你的软件可能要使用某一个端口,或者想查找某一个端口是否被占用.需要怎么做呢??这的确是一个比较烦恼的问题,我也此为这个苦恼过.但是通过查找man手册,还是同事的交流.总结出来两种 ...
- LInux维护一:VirtualMachine磁盘扩容
- Spring源码深度解析之事务
Spring源码深度解析之事务 目录 一.JDBC方式下的事务使用示例 (1)创建数据表结构 (2)创建对应数据表的PO (3)创建表和实体之间的映射 (4)创建数据操作接口 (5)创建数据操作接口实 ...
- Windows DHCP最佳实践(四)
这是Windows DHCP最佳实践和技巧的最终指南. 如果您有任何最佳做法或技巧,请在下面的评论中发布它们. 在本指南(四)中,我将分享以下DHCP最佳实践和技巧. 使用DHCP中继代理 防止恶意D ...
- React中的合成事件
React中的合成事件 React自己实现了一套高效的事件注册.存储.分发和重用逻辑,在DOM事件体系基础上做了很大改进,减少了内存消耗,简化了事件逻辑,并最大程度地解决了IE等浏览器的不兼容问题. ...