当前位置: 首页 > 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…...

四旋翼变形控制:RL与MPC在混合动力学中的对比

1. 四旋翼变形控制的技术挑战与解决方案四旋翼变形控制&#xff08;Quadrotor Morpho-Transition&#xff09;是当前机器人领域最具挑战性的前沿技术之一。这项技术使机器人能够在空中完成形态变换&#xff0c;实现从飞行模式到地面模式的平滑切换。想象一下&#xff0c;一架四…...

Visual Studio 项目属性页开发完全教程:从基础到高级

Visual Studio 项目属性页开发完全教程&#xff1a;从基础到高级 【免费下载链接】project-system The .NET Project System for Visual Studio 项目地址: https://gitcode.com/gh_mirrors/pr/project-system Visual Studio 项目属性页是开发者管理项目配置的核心界面&a…...

基于2D工程图几何特征与梯度提升模型的制造成本智能预测

1. 项目概述&#xff1a;从图纸到报价的智能革命在制造业&#xff0c;尤其是像汽车零部件这样的离散制造领域&#xff0c;报价速度直接决定了订单的生死。传统上&#xff0c;拿到一张新的2D工程图&#xff08;DWG格式&#xff09;&#xff0c;成本工程师需要花上几天甚至几周时…...

从STM32迁移到普冉PY32F003:UART代码移植保姆级教程(附HAL库对比)

从STM32到普冉PY32F003的UART代码迁移实战指南 1. 国产MCU替代浪潮下的技术选择 近年来&#xff0c;半导体行业的供应链波动促使更多工程师将目光投向国产MCU解决方案。普冉PY32F003系列作为Cortex-M0内核的代表产品&#xff0c;以48MHz主频、64KB Flash和8KB RAM的配置&#x…...

Yokogawa AAI835-H50/K4A00模拟输入/输出模块

Yokogawa AAI835-H50/K4A00 模拟输入/输出模块产品特点&#xff1a;通道配置&#xff1a;共8个通道&#xff0c;含4路模拟输入和4路模拟输出。信号类型&#xff1a;所有通道均支持4-20mA标准电流信号。HART通信&#xff1a;支持HART协议&#xff0c;可与智能现场设备双向数字通…...

MBTI性格测试

简介 MBTI&#xff08;Myers‑Briggs Type Indicator&#xff0c;迈尔斯‑布里格斯类型指标&#xff09;是基于荣格心理类型理论发展出的性格类型工具&#xff0c;由凯瑟琳库克布里格斯及其女儿伊莎贝尔布里格斯迈尔斯创建。它通过四对偏好维度将个体的认知与行为倾向归纳为 16…...

基于ESP32的AIS转WiFi转换器:实现NMEA 0183数据无线传输

1. 项目概述&#xff1a;从VHF-AIS接收器到iPad的无线桥梁作为一名经常在海上折腾电子设备的航海爱好者&#xff0c;我最近遇到了一个挺实际的需求&#xff1a;我的主力导航设备是iPad上的iSailor应用&#xff0c;它功能强大、界面友好&#xff0c;但有个“硬伤”——它需要通过…...

VMware ESXi 9.1.0.0集成NVME+网卡驱动版发布|新特性+驱动集成+部署升级+FAQ全指南

一、ESXi 9.1.0.0 正式版核心新特性 VMware ESXi 9.1.0.0&#xff08;2026 年 5 月发布&#xff09;是 vSphere 9.1 核心组件&#xff0c;聚焦硬件兼容扩展、性能跃升、安全加固、运维简化四大方向&#xff0c;重点强化 NVMe 存储与网卡生态适配&#xff0c;以下为关键更新&am…...

荣耀出征官方网站下载正版手游 翅膀养成细节玩法全方位讲解

玩荣耀出征的玩家都清楚&#xff0c;翅膀不仅是角色的颜值象征&#xff0c;更是提升整体战力的核心途径。很多新手玩家只顾着升级、刷装备&#xff0c;完全忽略翅膀养成&#xff0c;导致等级很高但战力始终上不去。还有不少玩家胡乱合成、盲目进阶&#xff0c;浪费了大量稀有翅…...

【深度解析】AI Coding 模型竞速:从 Claude Mythos 安全编码到 GPT-5.6 传闻,如何落地代码审查智能体

摘要 AI 编码模型正在从“代码补全”进入“复杂代码库理解、漏洞发现与自动修复”阶段。本文结合 Claude Mythos、Claude Opus 4.8 与 GPT-5.6 相关信息&#xff0c;解析新一代 Coding Agent 的技术趋势&#xff0c;并给出基于大模型 API 的代码安全审查实战方案。背景介绍&…...