每天一道leetcode:1192. 查找集群内的关键连接(图论困难tarjan算法)

今日份题目:

力扣数据中心有 n 台服务器,分别按从 0n-1 的方式进行了编号。它们之间以 服务器到服务器 的形式相互连接组成了一个内部集群,连接是无向的。用 connections 表示集群网络,connections[i] = [a, b] 表示服务器 ab 之间形成连接。任何服务器都可以直接或者间接地通过网络到达任何其他服务器。

关键连接 是在该集群中的重要连接,假如我们将它移除,便会导致某些服务器无法访问其他服务器。

请你以任意顺序返回该集群内的所有 关键连接

示例1

输入:n = 4, connections = [[0,1],[1,2],[2,0],[1,3]]
输出:[[1,3]]
解释:[[3,1]] 也是正确的。

示例2

输入:n = 2, connections = [[0,1]]
输出:[[0,1]]

提示

  • 2 <= n <= 105

  • n - 1 <= connections.length <= 105

  • 0 <= ai, bi <= n - 1

  • ai != bi

  • 不存在重复的连接

题目思路

根据关键连接的定义,我们可以将题目翻译为,找出删除会导致连通图不连通的点,进而翻译为找到删除后会导致图不连通的边的两点,也就是图论中所说的割边。使用tarjan算法找到割边。

tarjan算法是一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法。所谓强连通,就是说两个顶点可以相互通达。Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。

该题直接使用递归,没有涉及堆栈。其中有两个关键数组:dfn和low,dfn可以简单理解为记录我这个点是第几个被遍历到的(时间戳),low可以理解为我的父节点的时间戳。注意,是父节点,不是祖父甚至祖祖父。具体过程可以看我的代码注释。

这道题目有些难,我也是第一次接触到tarjan算法,欢迎懂的小伙伴在评论区科普一下,我也是从网上找的过程,但和本题的不太一样,我就直接读的代码,如果不对欢迎评论指出,谢谢!

代码

class Solution 
{
public:unordered_map<int,unordered_set<int>> connect;    vector<vector<int>> ans;
//------------------------ tarjan算法找割边 ------------------------//int dfn[200000]={0};      //节点搜索的次序编号,记录节点时间戳int low[200000]={0};      //子树能够追溯到的最早的栈中节点的次序号,即可以回溯到的最早的时间点int time=1;               //全局时间,时间戳//当dfn(u)=low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。//dfn的值表示第几个被遍历到//low的值表示最早的连接我的点,初始值与dfn一样,后续更新为相连的最小时间戳的那个点的low值//全局变量time用来表示遍历到第几个了,用于提供dfn的值//默认边的表示是u->vvoid tarjan(int u,int parent){//初始dfn和low的值都是时间戳dfn[u]=time;low[u]=time;time++;for(int v:connect[u]) //遍历u点的所有邻接点{if(v==parent) continue; //遍历到已经遍历过的节点了(把我引来的节点)if(dfn[v]==0) //由于初始化为0,所以等于0表示该节点还没有遍历过{tarjan(v,u); //判断邻接点的联通情况low[u]=min(low[u],low[v]); //low更新为与我相连的节点的最小时间戳//节点与每个相连的另一个节点比就能更新为相连的最小时间戳if(low[v]>dfn[u]) ans.push_back({u,v}); //是割边的两点的判断条件}else if(dfn[v]!=0) low[u]=min(low[u],dfn[v]); //该点遍历过了,只更新low}};vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) {                    for(auto x:connections) //将无向图转化为双向图便于使用tarjan算法{int u=x[0];int v=x[1];connect[u].insert(v);connect[v].insert(u);}tarjan(0,-1); //从0开始tarjan算法return ans;}
};

提交结果

欢迎大家在评论区讨论,如有不懂的部分,欢迎在评论区留言!

更新不易,宝子们点个赞支持下,谢谢!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/39959.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Quivr 基于GPT和开源LLMs构建本地知识库 (更新篇)

一、前言 自从大模型被炒的越来越火之后&#xff0c;似乎国内涌现出很多希望基于大模型构建本地知识库的需求&#xff0c;大概在5月底的时候&#xff0c;当时Quivr发布了第一个0.0.1版本&#xff0c;第一个版本仅仅只是使用LangChain技术结合OpenAI的GPT模型实现了一个最基本的…

升级STM32电机PID速度闭环编程:从F1到F4的移植技巧与实例解析

引言&#xff1a; 在嵌入式系统开发中&#xff0c;STM32系列微控制器广泛应用于各种应用领域。而对于直流有刷电机的控制&#xff0c;PID速度闭环是一种常用的控制方式。本文将以此为例&#xff0c;探讨如何从STM32F1系列移植到STM32F4系列&#xff0c;并详细介绍HAL库在不同型…

Python学习笔记_基础篇(十)_socket编程

本章内容 1、socket 2、IO多路复用 3、socketserver Socket socket起源于Unix&#xff0c;而Unix/Linux基本哲学之一就是“一切皆文件”&#xff0c;对于文件用【打开】【读写】【关闭】模式来操作。socket就是该模式的一个实现&#xff0c;socket即是一种特殊的文件&…

spring boot 简单整合 Redis

1.添加依赖<!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- commons-pool2 --><dependency><groupId>org.ap…

Linux安装Docker

一、Docker系统版本介绍 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 或 Windows 操作系统的机器上&#xff0c;也可以实现虚拟化。 容器是完全使用沙箱机制&#xff0c;相…

诚迈科技荣膺小米“最佳供应商奖”

近日&#xff0c;诚迈科技受邀参加小米战略合作伙伴HBR总结会。诚迈科技以尽职尽责的合作态度、精益求精的交付质量荣膺小米公司颁发的最佳供应商奖&#xff0c;其性能测试团队荣获优秀团队奖。 诚迈科技与小米在手机终端方向一直保持着密切的合作关系&#xff0c;涉及系统框架…

centOS 快速安装和配置 NVIDIA docker Container Toolkit

要在 CentOS 上正确安装和配置 NVIDIA Container Toolkit&#xff0c;您可以按照以下步骤进行操作&#xff0c;如果1和2都已经完成&#xff0c;可以直接进行第3步NVIDIA Container Toolkit安装配置。 1. 安装 NVIDIA GPU 驱动程序&#xff1a; 您可以从 NVIDIA 官方网站下载适…

【Java基础】Java对象的生命周期

【Java基础】Java对象的生命周期 一、概述 一个类通过编译器将一个Java文件编译为Class字节码文件&#xff0c;然后通过JVM中的解释器编译成不同操作系统的机器码。虽然操作系统不同&#xff0c;但是基于解释器的虚拟机是相同的。java类的生命周期就是指一个class文件加载到类…

Ubuntu安装MySQL Server提示Depends: mysql-server-5.5怎么解决

在 Ubuntu 安装 MySQL Server 时出现 Depends: mysql-server-5.5 的错误通常是因为系统中没有找到所需的软件包版本。这可能是因为软件包源中没有对应的版本或者软件包版本冲突等原因。解决这个问题的方法如下&#xff1a; 更新软件包列表&#xff1a; 在终端中运行以下命令&a…

python控制obs实现无缝切换场景!obs-websocket-py

前言 最近一直在研究孪生数字人wav2lip。目前成果可直接输入高清嘴型&#xff0c;2070显卡1分钟音频2.6分钟输出。在直播逻辑上可以做到1比1.3这样&#xff0c;所以现在开始研究直播。在逻辑上涉及到了无缝切换&#xff0c;看到csdn上有一篇文章还要vip解锁。。。那自己研究吧…

临时用工小程序:一款便捷的用工管理软件

随着企业对人力资源需求的不断增长&#xff0c;临时用工需求也日益旺盛。为了满足这一需求&#xff0c;我们研发了一款名为“临时用工小程序”的软件系统&#xff0c;旨在帮助企业实现临时用工的高效管理。 一、技术栈介绍 后端技术栈 本系统采用Java语言作为开发语言&#…

尚硅谷MySQL笔记 3-9

我不会记录的特别详细 大体框架 基本的Select语句运算符排序与分页多表查询单行函数聚合函数子查询 第三章 基本的SELECT语句 SQL分类 这个分类有很多种&#xff0c;大致了解下即可 DDL&#xff08;Data Definition Languages、数据定义语言&#xff09;&#xff0c;定义了…

项目难点:解决IOS调用起软键盘之后页面样式布局错乱问题

需求背景 &#xff1a; 开发了一个问卷系统重构项目&#xff0c;刚开始开发的为 PC 端&#xff0c;其中最头疼的一点无非就是 IE 浏览器的兼容适配性问题&#xff1b; 再之后项目经理要求开发移动端&#xff0c;简单的说就是写 H5 页面&#xff0c;到时候会内嵌在 App 应用、办…

multiple definition of......first defined here

一、背景 环境&#xff1a; 银河麒麟–ARM–GCC7.4.0 写了一个动态库&#xff0c;依赖opencv和freeImage等第三方库&#xff0c;用cmake进行编译。原本在centos6-x86-gcc7.5.0上面进行编译非常的顺利&#xff0c;但是拿到麒麟arm上面编译就提示了这个错误&#xff1a;这个报错…

Python conda命令

Windows下 Anaconda Prompt 这个东西就是用来管理Anaconda的&#xff0c;使用的是conda这样的一种命令 在Linux中&#xff0c;可以直接在终端中输入conda 命令 可以使用conda命令创建新的python环境&#xff08;python版本&#xff0c;包&#xff09;&#xff0c;新的环境与原…

Ruby软件外包开发语言特点

Ruby 是一种动态、开放源代码的编程语言&#xff0c;它注重简洁性和开发人员的幸福感。在许多方面都具有优点&#xff0c;但由于其动态类型和解释执行的特性&#xff0c;它可能不适合某些对性能和类型安全性要求较高的场景。下面和大家分享 Ruby 语言的一些主要特点以及适用的场…

【C语言】动态通讯录 -- 详解

⚪前言 前面详细介绍了静态版通讯录【C语言】静态通讯录 -- 详解_炫酷的伊莉娜的博客-CSDN博客&#xff0c;但是静态版通讯录的空间是无法被改变的&#xff0c;而且空间利用率也不高。为了解决静态通讯录这一缺点&#xff0c;这时就要有一个能够随着存入联系人数量的增加而增大…

Ansys Zemax | 手机镜头设计 - 第 1 部分:光学设计

本文是 3 篇系列文章的一部分&#xff0c;该系列文章将讨论智能手机镜头模组设计的挑战&#xff0c;从概念、设计到制造和结构变形的分析。本文是三部分系列的第一部分&#xff0c;将专注于OpticStudio中镜头模组的设计、分析和可制造性评估。&#xff08;联系我们获取文章附件…

Vue缓存路由组件

目录 一、使用 一、使用 作用&#xff1a;让不展示的路由组件保持挂载&#xff0c;不被销毁 <template><div><h2>Home组件内容</h2><div><ul class"nav nav-tabs"><li><router-link class"list-group-item"…

安防监控视频云存储平台EasyNVR通道频繁离线的原因排查与解决

安防视频监控汇聚EasyNVR视频集中存储平台&#xff0c;是基于RTSP/Onvif协议的安防视频平台&#xff0c;可支持将接入的视频流进行全平台、全终端分发&#xff0c;分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。为了满足用户的集成与二次开发需求&#xf…