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

图的割点、割边(Tarjan算法)

        深度优先搜索的利用。


        在一个无向连通图中,如果删掉某个顶点后,图不再连通(即任意两点之间不能互相到达),我们称这样的顶点为割点

        在一个无向连通图中,如果删掉某条边后,图不在连通,这就是割边

        我们来看一个例子:

重要城市

        我们已经掌握了敌人的城市地图,为了在战争中先发制人决定向敌人的某个城市上空投放炸弹,来切断敌人城市之间的通讯和补给,城市地图如下。

         

        肉眼可见,删除二号顶点后,图便不在连通。那么我们如何设计程序来判断呢?

        最直接的方法是遍历每一个顶点,判断该点删除后,其它顶点是否连通,用邻接表存储,时间复杂度为O(N(N+M))

        现在要讲的Tarjan算法,在朴素算法的基础上优化,可以把时间复杂度降低到O(N+M)

Tarjan算法(图的割点)

        Tarjan算法相较于朴素方法,我认为就是在深度搜索的时候已经处理了哪些是割点(因为遍历的时候肯定会遇到割点),而不需要再遍历n个顶点去删除所以它的时间复杂度去除了外面的N变成了O(N+M)

        为了突出Tarjan算法部分,我们先用邻接矩阵来写这道题,时间复杂度为O(N^2)

        所以最主要的就是深度搜索部分,我们先来想一下朴素方法的深度搜索,其实就是构成了一个生成树(每一个无向连通图都有生成树)

        本图的一个生成树如上所示,num数组来记录每个顶点的时间戳(每个结点的右上角,表示第几个被访问到),如num[3]=2,表示顶点3第二个被访问。

        正如前面所说遍历的时候肯定会遇到割点,如果生成树上的一个子结点在图中不经过它的父结点就不能访问已经遍历过的其它结点,那么它的父节点就肯定是割点了。(根节点没有父节点,时间戳最小,需要另外判断)

        下面这个难题就转变了,如果判断子节点不经过父节点访问其它节点。这里我们用一个low数组来存储一个节点在不经过父节点的情况下能访问到最远结点的时间戳。 

        对于某个顶点u,如果至少一个顶点v(即顶点的儿子),使得low[v]>=num[u](两个数组都是存的时间戳),那么u点为割点。

        对于本例,5号顶点的儿子只有6号结点,且low[6]的值为3,而5号顶点的时间戳为num[5]为5,low[6]<num[5],可以回到祖先,因此5号结点不是割点。 2号顶点的时间戳为num[2]为3,low[5]=3,low[5]==num[2],不可以回到祖先,因此2号结点不是割点。

        完整代码:(详细理解深度搜索部分)

#include<stdio.h>
int n,m;/*顶点数和边数*/
int root;/*根结点*/
int e[9][9]={0};/*邻接矩阵*/
int num[9]={0},low[9]={0},flag[9]={0};
/*num记录时间戳,low记录不经过父节点到达的最远时间戳
flag记录是否为割点*/int min(int a,int b)
{return a<b ? a:b;
}void dfs(int cur,int father,int index)
{int child=0;index++;num[cur]=index;low[cur]=index;for (int i = 1; i <= n; i++){if (e[cur][i]==1){if (num[i]==0)/*i顶点没有杯访问过*/{child++;/*子结点+1*/dfs(i,cur,index);/*继续往下遍历*/low[cur]=min(low[cur],low[i]);/*包含通过子节点访问的最早时间戳*/if (cur!=root && low[i]>= num[cur])/*当前结点不为根结点,子节点不能不通过父节点访问到之前的结点,该点为割点*//*不能为根结点是因为low[i]最小为root*/{flag[cur]=1;}else if(cur==root && child>=2)/*为根结点,且在生成树中(不是图),有两个儿子*//*生成树中有两个儿子肯定是割点,没有两个儿子也有可能是割点*/flag[cur]=1;}else if (i!=father)/*访问到的不是父节点,代表可以绕过了父节点*/{low[cur]=min(low[cur],num[i]);}     }}return ;
}int main()
{int x,y;scanf("%d %d",&n,&m);for (int i = 1; i <= m; i++){scanf("%d%d",&x,&y);e[x][y]=1;e[y][x]=1;/*无向图*/}root = 1;dfs(1,root,0);for (int i = 1; i <= n; i++){if (flag[i]==1){printf("%d ",i);}}return 0;
}

       

 输入格式:


        输入m+1行,第一行两个数n和m,n表示n个顶点,m表示m条边。接下来的m行,每行形如“a b”,用来表示一条边。

 输出格式:


        输出一行,一个数表示花费的最少银子数。

输入样例:

6 7

1 4

1 3

4 2

3 2

2 5

2 6

5 6

输出样例:

 2

图的割边

        如下图所示,左边的图没有割边,右边的图有割边:

        图的割边其实子需要修改上面代码中的一个部分将low[v]>=num[u]改为low[v]>num[u],即到达的顶点不包括其父结点和已经遍历的时间戳小于父结点的结点,这就证明该子节点与父节点相连的边为割边

        由于割边不需要额外判断是否为根节点,故判断那一部分可以删除。

        完整代码(注意输出部分):

#include<stdio.h>
int n,m;/*顶点数和边数*/
int root;/*根结点*/
int e[9][9]={0};/*邻接矩阵*/
int num[9]={0},low[9]={0};
/*num记录时间戳,low记录不经过父节点到达的最远时间戳*/int min(int a,int b)
{return a<b ? a:b;
}void dfs(int cur,int father,int index)
{index++;num[cur]=index;low[cur]=index;for (int i = 1; i <= n; i++){if (e[cur][i]==1){if (num[i]==0)/*i顶点没有杯访问过*/{dfs(i,cur,index);/*继续往下遍历*/low[cur]=min(low[cur],low[i]);/*包含通过子节点访问的最早时间戳*/if (low[i] > num[cur]){printf("%d-%d\n",cur,i);}}else if (i != father)/*访问到的不是父节点,代表可以绕过了父节点*/{low[cur]=min(low[cur],num[i]);}     }}return ;
}int main()
{int x,y;scanf("%d %d",&n,&m);for (int i = 1; i <= m; i++){scanf("%d%d",&x,&y);e[x][y]=1;e[y][x]=1;/*无向图*/}root = 1;dfs(1,root,0);    return 0;
}

输入格式:


        输入m+1行,第一行两个数n和m,n表示n个顶点,m表示m条边。接下来的m行,每行形如“a b”,用来表示一条边。

 输出格式:


        输出一行,一个数表示花费的最少银子数。

输入样例:

6 6

1 4

1 3

4 2

3 2

2 5

5 6

输出样例:

5-6

2-5

参考文献: 

《啊哈!算法》

相关文章:

图的割点、割边(Tarjan算法)

深度优先搜索的利用。 在一个无向连通图中&#xff0c;如果删掉某个顶点后&#xff0c;图不再连通&#xff08;即任意两点之间不能互相到达&#xff09;&#xff0c;我们称这样的顶点为割点。 在一个无向连通图中&#xff0c;如果删掉某条边后&#xff0c;图不在连通&#xff0…...

算法学习(十四)—— 二叉树的深度搜索(DFS)

目录 关于dfs 部分OJ题详解 2331. 计算布尔二叉树的值 129. 求根节点到叶节点数字之和 814. 二叉树剪枝 98. 验证二叉搜索树 230. 二叉搜索树中第K小的元素 257. 二叉树的所有路径 关于dfs 算法学习&#xff08;十二&#xff09;—— 递归&#xff0c;搜索&#xff0c…...

【vue2】封装自定义的日历组件(三)之基础添加月份的加减定位到最新月份的第一天

我们在切换月份的时候&#xff0c;希望高亮显示在每个月的第一天上面&#xff0c;这样的效果我们要怎么来实现&#xff0c;其实也很简单&#xff0c;我们先看下实现的效果 实现效果 代码实现 原理就是获取到每月的第一天日期&#xff0c;然后再跟整个的数据进行对比&#xff…...

LabVIEW偏心圆筒流变仪测控系统

偏心圆筒流变仪是一种专门研究聚合物熔体在复杂流场中特殊流变行为的先进设备。通过结合硬件控制与LabVIEW软件开发&#xff0c;本系统实现了对流变仪功能的精准控制与数据采集&#xff0c;进一步提高了聚合物加工过程的研究精度和效率。 项目背景 传统的流变测量设备多集中于…...

Runloop

假设你的项目中有关tableView&#xff0c;然后还有一个定时器timer在执行&#xff0c;定时器代码如下&#xff1a; var num 0override func viewDidLoad() {super.viewDidLoad()let timer Timer(timeInterval: 1,target: self,selector: #selector(self.run),userInfo: nil,r…...

SpringBoot的Bean类三种注入方式(附带LomBok注入)

SpringBoot的Bean类三种注入方式&#xff08;附带LomBok注入&#xff09; 在 Spring Boot 中&#xff0c;Bean 的注入方式主要包括构造函数注入&#xff08;Constructor Injection&#xff09;、字段注入&#xff08;Field Injection&#xff09;以及 Setter 方法注入&#xf…...

开源向量数据库介绍说明

开源向量数据库 Milvus 特点&#xff1a;分布式、高性能&#xff0c;支持亿级向量检索。 支持的数据类型&#xff1a;文本、图像、音频、视频等。 使用场景&#xff1a;推荐系统、语义搜索、图像搜索。 数据存储后端&#xff1a;支持多种后端&#xff0c;如 SQLite、MySQL、Pos…...

【前端】深度解析 JavaScript 中的 new 关键字与构造函数

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;构造函数的核心特性&#x1f4af;new 关键字的执行机制&#x1f4af;实例代码与详细解析代码示例代码逐步解析 &#x1f4af;new 的内部执行模拟执行过程的详细解析 &am…...

2024年华中杯数学建模C题基于光纤传感器的平面曲线重建算法建模解题全过程文档及程序

2024年华中杯数学建模 C题 基于光纤传感器的平面曲线重建算法建模 原题再现 光纤传感技术是伴随着光纤及光通信技术发展起来的一种新型传感器技术。它是以光波为传感信号、光纤为传输载体来感知外界环境中的信号&#xff0c;其基本原理是当外界环境参数发生变化时&#xff0c…...

使用 `typing_extensions.TypeAlias` 简化类型定义:初学者指南

使用 typing_extensions.TypeAlias 简化类型定义&#xff1a;初学者指南 什么是 TypeAlias&#xff1f;安装 typing_extensions示例代码&#xff1a;如何使用 TypeAlias示例 1&#xff1a;为简单类型定义别名示例 2&#xff1a;为复杂类型定义别名示例 3&#xff1a;结合 Union…...

如何快速批量把 PDF 转为 JPG 或其它常见图像格式?

在某些特定场景下&#xff0c;将 PDF 转换为 JPG 图片格式却具有不可忽视的优势。例如&#xff0c;当我们需要在不支持 PDF 查看的设备或软件中展示文档内容时&#xff0c;JPG 图片能够轻松被识别和打开&#xff1b;此外&#xff0c;对于一些网络分享或社交媒体发布的需求&…...

如何在组织中塑造和强化绩效文化?

在组织中塑造和强化绩效文化是一个系统性的工程。 一、明确绩效目标与期望 设定清晰目标 组织应根据自身战略规划&#xff0c;将长期目标分解为具体、可衡量、可实现、相关联、有时限&#xff08;SMART&#xff09;的短期和中期绩效目标。例如&#xff0c;一家连锁餐饮企业的…...

OllyDbg、CE简单介绍

基础知识&#xff1a; 想要破解软件&#xff0c;需要一些基础知识&#xff1a; 文件格式&#xff1a;Windows对应PE、Linux对应ELF、IOS对应Mash-0。文件格式是指操作系统规定的每个段&#xff08;代码段、数据段、堆、栈&#xff09;的大小、顺序等信息。 汇编语言&#xff1…...

Python函数——函数的返回值定义语法

一、引言 在Python中&#xff0c;函数的返回值是其核心功能之一&#xff0c;它使得函数能够将计算结果传递给调用者&#xff0c;进而推动程序的逻辑和功能实现。理解和掌握函数的返回值语法&#xff0c;不仅能够提高代码的模块化和可读性&#xff0c;还能使程序更加高效和灵活…...

【Pandas】pandas isna

Pandas2.2 General Top-level missing data 方法描述isna(obj)用于检测数据中的缺失值isnull(obj)用于检测数据中的缺失值notna(obj)用于检测数据中的非缺失值notnull(obj)用于检测数据中的非缺失值 pandas.isna() pandas.isna() 是 Pandas 库中的一个函数&#xff0c;用于…...

mysql 数据库表的大小

mysql 数据库表的大小 Mysql 查看数据库各个表占用空间 mysql如何查看数据库所有表大小 在MySQL中&#xff0c;要查看数据库所有表的大小&#xff0c;可以使用以下方法&#xff1a; 方法一&#xff1a;使用information_schema数据库 首先&#xff0c;通过命令行或图形界面…...

(6)JS-Clipper2之ClipperOffset

1. 描述 ClipperOffset类封装了对打开路径和关闭路径进行偏移(膨胀/收缩)的过程。 这个类取代了现在已弃用的OffsetPaths函数&#xff0c;该函数不太灵活。可以使用不同的偏移量(增量)多次调用Execute方法&#xff0c;而不必重新分配路径。现在可以在一次操作中对开放和封闭路…...

如何在Ubuntu中利用repo和git地址下载获取imx6ull的BSP

01-设置git的用户名和邮箱 git config --global user.name "suwenhao" git config --global user.email "2487872782qq.com"这里不设置的话后面在第5步的repo配置中还是会要求输入&#xff0c;而且以后进行相关操作都要输入&#xff0c;不妨现在就进行配置…...

Ruby On Rails 笔记5——常用验证下

3.Validation Options 3.1 :allow_nil 当验证值为nil时:allow_nil选项会跳过验证 class Coffee < ApplicationRecordvalidates :size, inclusion: { in: %w(small medium large),message: "%{value} is not a valid size" }, allow_nil: true end irb> Cof…...

JS听到了因果的回响

这是我学习JS的第11天了&#xff0c;&#xff0c;&#xff0c;我现在赶着周末学JS&#xff0c;然后还有二十多天就期末了呵呵呵。。。 图片切换模块 思路分析&#xff1a; 这是实现的代码&#xff0c;建议还是把不同的变量定义出来比较合适&#xff1a; //获取三个盒子// 小盒…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...