当前位置: 首页 > news >正文

【算法模板】图论:Tarjan算法求割边割点

概念

割边(Bridge 或 Cut Edge)

定义

  • 在一个无向连通图中,如果删除某条边后,图不再连通(即任意两点之间不能相互到达),则称该边为割边。割边也被称为桥,因为它像桥梁一样连接着图的两部分,一旦移除,这两部分就被隔断了。

特性

  • 割边只存在于无向连通图中。
  • 删除割边会导致图的连通分量数量增加。
  • 割边是图中的一个“薄弱环节”,对于图的连通性有重要影响。

边双连通分量(Edge Biconnected Component)

  • 定义
    • 一个无向图的边双连通分量是一个极大连通子图,删除任意一条边后,图仍然连通。
    • 类似于点双连通分量,边双连通分量中的任意两个节点之间都有两条不相交的边(即,如果删除一条边,仍然可以保持连通)。
  • 性质
    • 边双连通分量的每个分量都是连通的。
    • 边双连通分量可用于分析图中冗余的边以及提高图的可靠性。

割点(Articulation Point 或 Cut Vertex)

定义

  • 在一个无向连通图中,如果删除了某个顶点后,图不再连通(即任意两点之间不能相互到达),则称该顶点为割点。割点也被称为关节点,因为它像关节一样连接着图的不同部分,一旦移除,这些部分就被分开了。

特性

  • 割点同样只存在于无向连通图中。
  • 删除割点会导致图的连通分量数量增加或减少(具体取决于割点的位置和图的结构)。
  • 割点是图中的一个重要节点,对于维护图的连通性至关重要。

点双连通分量(Vertex Biconnected Component)

  • 定义

    • 一个无向图的点双连通分量是一个极大连通子图,删除任意一个节点后,图仍然连通。
    • 换句话说,点双连通分量中的任意两个节点之间都有两条不相交的路径(即,如果删除一个节点,仍然可以保持连通)。
  • 性质

    • 点双连通分量的每个分量都是连通的。
    • 点双连通分量可用来检测图中的割点(即删除后会增加连通分量的节点)。

割点与割边的关系

  • 存在割点时必有割边:如果一个节点是割点,那么至少存在一条通过该节点的割边。删除割点会导致图分裂为多个部分,每个部分之间至少存在一条割边。

  • 割边连接的节点可能是割点:割边的两个端点节点至少有一个可能是割点。特别是在边的两个端点是不同的双连通分量时,这两个节点通常是割点。

  • 独立的关系:虽然割点和割边紧密相关,但它们也可以独立存在。一个图可以有割点而没有割边,或者有割边而没有割点。例如,星型图的中心节点是割点,但星型图的每条边都是割边。

Tarjan算法

算法思想

  1. DFS 访问顺序: 每个节点都有一个 dfn 值,表示节点在 DFS 中被访问的时间戳(第几个被访问)。同时,还有一个 low 值,表示节点能通过回边或子节点到达的最早访问的节点的时间戳。
  2. 割点判定
    • 对于根节点,如果它有两个或两个以上的子树,则它是割点。
    • 对于非根节点,如果某个子节点的 low 值不小于该节点的 dfn 值,则该节点是割点。
  3. 割边判定: 如果某个节点 u 和它的子节点 v 之间的边满足 low[v] > dfn[u],则边 (u, v) 是割边。

算法步骤

  1. 初始化 dfnlow 数组,初始值为 -1,表示未被访问。初始化一个时间戳变量 time 为 0。
  2. 使用 DFS 遍历图,对于每个未被访问的节点调用 DFS 函数。
  3. 在 DFS 函数中:
    • 设置当前节点的 dfnlow 值为当前时间戳,并将时间戳加 1。
    • 对于每个邻接节点,如果该邻接节点未被访问,递归调用 DFS 函数,更新当前节点的 low 值。
    • 如果邻接节点已被访问且不是父节点,更新当前节点的 low 值为邻接节点的 dfn 值。
    • 在返回时,根据 low 值判断是否是割点或割边。
  4. 记录所有割点和割边。

算法模板

// 求解割点的函数
vector<int> findCutPoints(const vector<vector<int>> &graph) {int n = graph.size();vector<int> cutPoints; // 存储割点vector<int> dfn(n, -1), low(n), parent(n, -1); // 初始化 dfn, low, parent 数组vector<bool> visited(n, false); // 记录节点是否已被访问int time = 0; // 时间戳// DFS 函数function<void(int)> dfs = [&](int u) {visited[u] = true; // 标记节点 u 为已访问dfn[u] = low[u] = time++; // 设置 dfn 和 low 值int childCount = 0; // 子节点数量bool isCutPoint = false; // 是否为割点// 遍历邻接节点for (int v : graph[u]) {if (!visited[v]) { // 如果 v 未被访问parent[v] = u; // 设置 v 的父节点为 udfs(v); // 递归调用 DFSchildCount++; // 增加子节点数量// 更新 low[u]low[u] = min(low[u], low[v]);// 判断是否为割点if (parent[u] == -1 && childCount > 1) { // 根节点且有两个以上子树isCutPoint = true;}if (parent[u] != -1 && low[v] >= dfn[u]) { // 非根节点且满足条件isCutPoint = true;}} else if (v != parent[u]) { // 如果 v 已被访问且不是父节点low[u] = min(low[u], dfn[v]); // 更新 low[u]}}// 如果是割点,加入结果if (isCutPoint) {cutPoints.push_back(u);}};// 遍历每个节点,进行 DFSfor (int i = 0; i < n; ++i) {if (!visited[i]) {dfs(i);}}return cutPoints; // 返回割点列表
}// 求解割边的函数
vector<pair<int, int>> findBridges(const vector<vector<int>> &graph) {int n = graph.size();vector<pair<int, int>> bridges; // 存储割边vector<int> dfn(n, -1), low(n), parent(n, -1); // 初始化 dfn, low, parent 数组vector<bool> visited(n, false); // 记录节点是否已被访问int time = 0; // 时间戳// DFS 函数function<void(int)> dfs = [&](int u) {visited[u] = true; // 标记节点 u 为已访问dfn[u] = low[u] = time++; // 设置 dfn 和 low 值// 遍历邻接节点for (int v : graph[u]) {if (!visited[v]) { // 如果 v 未被访问parent[v] = u; // 设置 v 的父节点为 udfs(v); // 递归调用 DFS// 更新 low[u]low[u] = min(low[u], low[v]);// 判断是否为割边if (low[v] > dfn[u]) {bridges.push_back({u, v}); // 记录割边}} else if (v != parent[u]) { // 如果 v 已被访问且不是父节点low[u] = min(low[u], dfn[v]); // 更新 low[u]}}};// 遍历每个节点,进行 DFSfor (int i = 0; i < n; ++i) {if (!visited[i]) {dfs(i);}}return bridges; // 返回割边列表
}

例题

P3388 【模板】割点(割顶)
给出一个 n 个点,m 条边的无向图,求图的割点。

#include <bits/stdc++.h>
using namespace std;
vector<int> findCutPoints(const vector<vector<int>> &graph);
signed main() {int n,m;cin>>n>>m;vector<vector<int>> G(n+1);while(m--){int u,v;cin>>u>>v;G[u].push_back(v);G[v].push_back(u);}vector<int> CutPoints=findCutPoints(G);cout<<CutPoints.size()<<endl;sort(CutPoints.begin(),CutPoints.end());for(int p:CutPoints)cout<<p<<' ';return 0;
}

P1656 炸铁路
将军uim需要选择一条铁路进行炸毁,以使得B国的物流系统瘫痪,导致至少存在两个城市无法通过铁路相互到达。要选择的铁路被称为“关键铁路”。

#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> findBridges(const vector<vector<int>> &graph);
signed main() {int n,m;cin>>n>>m;vector<vector<int>> G(n+1);while(m--){int u,v;cin>>u>>v;G[u].push_back(v);G[v].push_back(u);}vector<pair<int, int>> Bridges=findBridges(G);for(auto&[x,y]:Bridges)if(x>y)swap(x,y);sort(Bridges.begin(),Bridges.end());for(auto[x,y]:Bridges)cout<<x<<' '<<y<<endl;return 0;
}

相关文章:

【算法模板】图论:Tarjan算法求割边割点

概念 割边&#xff08;Bridge 或 Cut Edge&#xff09; 定义&#xff1a; 在一个无向连通图中&#xff0c;如果删除某条边后&#xff0c;图不再连通&#xff08;即任意两点之间不能相互到达&#xff09;&#xff0c;则称该边为割边。割边也被称为桥&#xff0c;因为它像桥梁…...

如何在IDEA上使用JDBC编程【保姆级教程】

目录 前言 什么是JDBC编程 本质 使用JDBC编程的优势 JDBC流程 如何在IEDA上使用JDBC JDBC编程 1.创建并初始化数据源 2.与数据库服务器建立连接 3.创建PreparedStatement对象编写sql语句 4.执行SQL语句并处理结果集 executeUpdate executeQuery 5.释放资源 前言 在…...

linux web系统安装常见问题解决,租房系统为案例

Warning: require(): open_basedir restriction in effect. 一、执行文件权限 网站目录下 open_basedir增加执行路径 二、文件夹权限放行 三、安装基础环境 composer install 四、数据合并 php think migrate:run 20200402094148 AdminUser: migrating 20200402094148 A…...

Linux驱动开发—平台总线模型详解

文章目录 1.平台总线介绍1.1平台总线模型的组成部分1.2平台总线模型的优势 2.使用平台总线模型开发驱动2.1注册platform设备2.2注册platform驱动2.3效果演示 1.平台总线介绍 Linux 平台总线模型&#xff08;Platform Bus Model&#xff09;是一种设备驱动框架&#xff0c;用于…...

说一下网络层,传输层,数据链路层做什么的,之间的关系?

网络层主要负责为数据包选择最佳路径&#xff0c;将数据从源主机传输到目标主机。它的关键任务包括路由选择、拥塞控制和网络互联等。通过网络层的功能&#xff0c;不同网络之间能够实现通信和数据传输。 传输层的作用是在源端和目的端之间提供可靠或不可靠的端到端的数据传输…...

解锁AI新纪元:Milvus Cloud与Zilliz Cloud的高可用之道

在当今数字化时代,系统的持续稳定运行与数据的即时访问性已成为衡量技术服务质量的关键指标。面对复杂多变的运行环境,包括电力波动、网络故障乃至人为操作失误等不可预见因素,数据库系统的高可用性(High Availability, HA)成为了保障业务连续性的重要基石。特别是在大数据…...

svn安装

579 ​​yum install subversion 580 rpm -qa|grep subversion 581 yum -y install subversion 582 rpm -ql subversion 583 /usr/bin/svnversion --version 584 mkdir /data/svnrepos 585 svnadmin create /data/svnrepos/abc 586 svnadmin create /data/svnrepos/gzss 587 cd…...

【隐私计算篇】混淆电路之深入浅出

入门隐私计算的阶段&#xff0c;一般都会涉及对于混淆电路的学习&#xff0c;这是因为混淆电路是多方安全计算中的基础密码原语&#xff0c;也是隐私保护中重要的技术。为了帮助更好地理解混淆电路的原理&#xff0c;今天对其进行原理以及相关优化手段进行解析和分享。 1. 混淆…...

基于GRU神经网络的微博分类预测

目录 背影 摘要 LSTM的基本定义 LSTM实现的步骤 gru的原理 GRU神经网络微博分类 结果分析 展望 参考论文 背影 传统的方法微博分类预测准确率低,为提高精度,本文用gru进行预测 摘要 LSTM原理,GRU原理,MATALB编程gru的微博分类预测 LSTM的基本定义 LSTM是一种含有LST…...

LVS-DR模式集群:案例与概念

DR模式&#xff08;直接路由&#xff09; 概念 Direct Routing&#xff0c;简称DR模式采用半开放式的网络结构&#xff0c;与TUN模式的结构类似&#xff0c;但内网服务器并不是分散在各地&#xff0c;而是与调度器位于同一个物理网络负载调度器与内网服务器通过本地网络连接&a…...

拓扑排序:Kahn算法与DFS算法

引言 拓扑排序是有向无环图&#xff08;DAG&#xff09;中的一种线性排序&#xff0c;使得对于图中的每一条有向边 ( u \rightarrow v )&#xff0c;顶点 ( u ) 在排序中出现在顶点 ( v ) 之前。本文将详细介绍两种实现拓扑排序的算法&#xff1a;Kahn算法和基于深度优先搜索&…...

图像处理 -- Sobel滤波器的实现原理与使用案例

Sobel滤波器 概述 Sobel滤波器是一种边缘检测方法&#xff0c;用于图像处理和计算机视觉领域。它通过计算图像灰度值的梯度来检测边缘。Sobel滤波器结合了高斯平滑和微分操作&#xff0c;以减少噪声并增强边缘检测效果。 实现原理 Sobel滤波器通过使用两个3x3卷积核&#x…...

机器学习 第10章-降维与度量学习

机器学习 第10章-降维与度量学习 10.1 k近邻学习 k近邻(k-Nearest Neighbor,简称kNN)学习是一种常用的监督学习方法其工作机制非常简单:给定测试样本&#xff0c;基于某种距离度量找出训练集中与其最靠近的k个训练样本&#xff0c;然后基于这k个“邻居”的信息来进行预测。通…...

linux驱动:(7)物理地址到虚拟地址映射

单片机、裸机、linux操控硬件方法 在单片机和裸机中操作硬件是通过指针来对寄存器赋值来进行操控 但对于linux中不能这样&#xff0c;不能直接对物理地址直接修改&#xff0c;因为linux使能了mmu&#xff0c;所以不能直接菜操作物理地址 如果要操作硬件&#xff0c;需要先把…...

浏览器用户文件夹详解 - Preferences(十)

1.Preferences简介 1.1 什么是Preferences文件&#xff1f; Preferences文件是Chromium浏览器中用于存储用户个性化设置和配置的一个重要文件。每当用户在浏览器中更改设置或安装扩展程序时&#xff0c;这些信息都会被记录在Preferences文件中。通过这些记录&#xff0c;浏览…...

Robot Operating System——电池电量通知

大纲 应用场景定义字段解释 案例 sensor_msgs::msg::BatteryState 是 ROS 2 中定义的消息类型&#xff0c;用于表示电池状态。它包含了电池电量、电压、电流、温度等信息。 应用场景 机器人 电池监控&#xff1a;在移动机器人中&#xff0c;电池是主要的电源。BatteryState 消…...

二进制安装docker

目录 一、准备 Docker CE 二进制包 二、解压.tgz包 三、复制二进制文件到/usr/bin/目录 四、创建用户组 五、配置相关服务配置文件 六、拷贝配置文件到指定目录 七、启动 dockerd 服务进程 八、shell脚本一键安装 一、准备 Docker CE 二进制包 https://download.docker…...

@SpringBootConfiguration重复加载报错

Junit单元测试Test启动报错&#xff0c;SpringBootConfiguration注解重复问题排查&#xff1a; SpringBootApplication 注解的 exclude 属性用于排除特定的自动配置类&#xff0c;而不是用于排除主配置类本身。因此&#xff0c;不能通过 exclude 属性来排除主配置类的加载。 …...

【SpringBoot】数据验证之分组校验

分组校验 在不同情况下&#xff0c;可能对JavaBean对象的数据校验规则有所不同&#xff0c;有时需要根据数据状态对JavaBean中的某些属性字段进行单独验证。这时就可以使用分组校验功能&#xff0c;即根据状态启用一组约束。 Hibernate Validator的注解提供了groups参数&#…...

MySQL Galera Cluster 部署与介绍

目录 主要特点 组件 一. 环境准备 二. 配置 1. 配置 galera1 主机的my.cnf的文件 2. 配置 galera2 主机的my.cnf的文件 3. 配置 galera3 主机的my.cnf的文件 4. 在给galera1 主机的my.cnf的文件增加节点 5. 写入数据验证同步 6. 配置 galera4 主机的my.cnf的文件 M…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Go语言多线程问题

打印零与奇偶数&#xff08;leetcode 1116&#xff09; 方法1&#xff1a;使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...