Leetcode 1489. 找到最小生成树里的关键边和伪关键边

1.题目基本信息

1.1.题目描述

给你一个 n 个点的带权无向连通图,节点编号为 0 到 n-1 ,同时还有一个数组 edges ,其中 edges[i] = [fromi, toi, weighti] 表示在 fromi 和 toi 节点之间有一条带权无向边。最小生成树 (MST) 是给定图中边的一个子集,它连接了所有节点且没有环,而且这些边的权值和最小。

请你找到给定图中最小生成树的所有关键边和伪关键边。如果从图中删去某条边,会导致最小生成树的权值和增加,那么我们就说它是一条关键边。伪关键边则是可能会出现在某些最小生成树中但不会出现在所有最小生成树中的边。

请注意,你可以分别以任意顺序返回关键边的下标和伪关键边的下标。

1.2.题目地址

https://leetcode.cn/problems/find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree/description/

2.解题方法

2.1.解题思路

无向图的连通性质:取权值为w的边,让小于w的边构成一个一个的连通分量comps,将每个连通分量comp作为一个节点,将w大小的节点与comps这些节点重新构建一个图,记为compG。

compG中的桥即为关键边;w大小的边的两端如果在同一个连通分量内,则既不是关键边也不是伪关键边;余下的都是伪关键边。

2.2.解题步骤

解题步骤请看代码注释

3.解题代码

Python代码

# # ==> 并查集模板(附优化)
class UnionFind():def __init__(self):self.roots={}self.setCnt=0   # 连通分量的个数# Union优化:存储根节点主导的集合的总节点数self.rootSizes={}def add(self,x):if x not in self.roots:self.roots[x]=xself.rootSizes[x]=1self.setCnt+=1def find(self,x):root=xwhile root != self.roots[root]:root=self.roots[root]# 优化:压缩路径while x!=root:temp=self.roots[x]self.roots[x]=rootx=tempreturn rootdef union(self,x,y):rootx,rooty=self.find(x),self.find(y)if rootx!=rooty:# 优化:小树合并到大树上if self.rootSizes[rootx]<self.rootSizes[rooty]:self.roots[rootx]=rootyself.rootSizes[rooty]+=self.rootSizes[rootx]else:self.roots[rooty]=rootxself.rootSizes[rootx]+=self.rootSizes[rooty]self.setCnt-=1from typing import List
class UndirectedGraphTarjan2():def __init__(self,graph:List[int:List[int]],graphEdges:List[int:List[int]]):self.length=len(graph)self.graph=graph    # 邻接表self.graphEdges=graphEdges  # 邻接表同结构的边self.dfn=[-1]*self.lengthself.low=[-1]*self.lengthself.bridges=[]self.timestamp=0def tarjan(self):for i in range(self.length):if self.graph[i]!=-1:self.tarjanDfs(i,-1)def tarjanDfs(self,node:int,fatherEdge:int):self.dfn[node]=self.low[node]=self.timestampself.timestamp+=1for i in range(len(self.graph[node])):subNode,edge=self.graph[node][i],self.graphEdges[node][i]   # 这里边是node指向subNode的边if self.dfn[subNode]==-1:self.tarjanDfs(subNode,edge)self.low[node]=min(self.low[node],self.low[subNode])if self.dfn[node]<self.low[subNode]:self.bridges.append(edge)elif edge!=fatherEdge:self.low[node]=min(self.low[node],self.low[subNode])from collections import defaultdict
class Solution:def findCriticalAndPseudoCriticalEdges(self, n: int, edges: List[List[int]]) -> List[List[int]]:edgesLength=len(edges)# 将所有的边编号并获取点->边id的映射for i in range(edgesLength):edges[i].append(i)# 将所有的边按权值从小到大进行排序edges.sort(key=lambda x:x[2])# 构建所有点的并查集(不用进行连接)uf=UnionFind()for i in range(n):uf.add(i)# 初始化所有边的标签为-1(1为关键边,0则两者都不是,最后还是-1的为伪关键边)labels=[-1]*edgesLength# 遍历所有的相同权值的边组edges[i,j)i=0while i<edgesLength:# 获取j的值j=iwhile j<edgesLength and edges[i][2]==edges[j][2]:j+=1# 将各个点按并查集分成m个连通分量,每个连通分量为新图compG中的一个节点,并给每个连通分量初始化需要inode2CompId={}compCnt=0for k in range(i,j):node1,node2,weight,edgeId=edges[k]node1Root,node2Root=uf.find(node1),uf.find(node2)if node1Root!=node2Root:if node1Root not in node2CompId:node2CompId[node1Root]=compCntcompCnt+=1if node2Root not in node2CompId:node2CompId[node2Root]=compCntcompCnt+=1else:labels[edgeId]=0    # 改变既不是关键边,也不是伪关键边# print(node2CompId)# 构建邻接表形式的compG和对应的边的idcompG=defaultdict(list)compGEids=defaultdict(list)for k in range(i,j):node1,node2,weight,edgeId=edges[k]node1Root,node2Root=uf.find(node1),uf.find(node2)if node1Root!=node2Root:compId1,compId2=node2CompId[node1Root],node2CompId[node2Root]compG[compId1].append(compId2)compGEids[compId1].append(edgeId)compG[compId2].append(compId1)compGEids[compId2].append(edgeId)# print(compCnt, compG, compGEids)ugt2=UndirectedGraphTarjan2(compG, compGEids)ugt2.tarjan()bridges=ugt2.bridges# print("bridges",bridges)# 将桥标记为1for bridge in bridges:labels[bridge]=1# 遍历[i,j)之间的边。如果该边是compG的桥,则该边是关键边;如果该边首尾连接同一个连通分量节点,则既不是关键边,也不是伪关键边;for k in range(i,j):node1,node2,weight,edgeId=edges[k]uf.union(node1,node2)# 更新ii=j# 标记完成后,剩下的没有标记的边即为伪关键边# 返回结果# print(labels)result=[[],[]]for i in range(edgesLength):if labels[i]==1:result[0].append(i)elif labels[i]==-1:result[1].append(i)return result

4.执行结果

在这里插入图片描述

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

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

相关文章

MFC扩展库BCGControlBar Pro v35.1新版亮点:改进网格控件性能

BCGControlBar库拥有500多个经过全面设计、测试和充分记录的MFC扩展类。 我们的组件可以轻松地集成到您的应用程序中&#xff0c;并为您节省数百个开发和调试时间。 BCGControlBar专业版 v35.1已全新发布了&#xff0c;这个版本改进网格控件的性能、增强工具栏编辑器功能等。 …

【puppeteer】wvp-puppeteer制作 过程

目录 最后的结论 制作windows&ubuntu的docker 重启桌面上的docker 命令重启 通过 Docker Desktop 图形界面重启 制作centos docker 测试 参考文档 最后的结论 ubuntu && windows 使用 dualvenregistry:5000/wvp-puppeteer:1.0 centos7 使用&#xff1a;…

通过OpenCV实现 Lucas-Kanade 算法

目录 简介 Lucas-Kanade 光流算法 实现步骤 1. 导入所需库 2. 视频捕捉与初始化 3. 设置特征点参数 4. 创建掩模 5. 光流估计循环 6. 释放资源 结论 简介 在计算机视觉领域&#xff0c;光流估计是一种追踪物体运动的技术。它通过比较连续帧之间的像素强度变化来估计图…

第6篇:无线与移动网络

目录 引言 6.1 无线网络的基础概念 6.2 无线局域网&#xff08;WLAN&#xff09;与IEEE 802.11 6.3 蓝牙与无线个域网&#xff08;WPAN&#xff09; 6.4 无线城域网&#xff08;WMAN&#xff09;与WiMax 6.5 ZigBee与智能家居 6.6 移动蜂窝网络&#xff08;3G/4G/5G&…

【Linux】总线-设备-驱动模型

背景 前面&#xff0c;我们介绍了写驱动代码的一些常规步骤&#xff0c;并且也写了最基本的驱动代码&#xff0c;但是那些代码存在着问题&#xff0c;我们将硬件的信息都写进了驱动里了&#xff0c;如果我们在杂项设备驱动中控制led&#xff0c;那么会在硬件操作接口中包含硬件…

【SQL实验】数据库、表、模式的SQL语句操作

完整代码在文章末尾 1、数据库的建立、删除和修改操作 &#xff08;1&#xff09;使用SQL语句创建数据库EDUC&#xff0c;并进行如下设置&#xff1a; 数据库文件和日志文件的逻辑名称分别为&#xff1a;Student_data和Student_log&#xff1b;数据文件的物理文件名为‘C:\DA…

基于Java语言的培训平台+学习平台+在线学习培训系统+教育平台+教育学习系统+课程学习平台

简述 企业培训平台企业考试系统培训平台考试系统企业大学企业视频网站视频学习平台 介绍 企业培训平台支持企业培训考试全流程&#xff0c;在线学习、在线考试&#xff0c;成熟的企业培训考试解决方案&#xff0c;充分满足企业培训需求。 独立部署&#xff0c;仅内部员工登录…

【热门】智慧果园管理系统解决方案

随着科技的进步,原有农业种植方式已经不能满足社会发展的需要,必须对传统的农业进行技术更新和改造。经过多年的实践,人们总结出一种新的种植方法——温室农业,即“用人工设施控制环境因素,使作物获得最适宜的生长条件,从而延长生产季节,获得最佳的产出”。这种农业生产方式…

03.顺序表实现

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储&#xff0c;在数组上完成数据的增删改查。一般见到的顺序表都是在结构体中定义的数组&#xff0c;只是比普通数组多了增删改查等一些其他功能函数。 上节已经介绍了顺序表有…

【android studio】Gradle和Gradle插件版本关系/配置/常见ERR示例

参考链接&#xff1a; Android之Gradle和Gradle插件区别及联系 grdle 的安装与配置 、gradle和jdk版本对应关系 Android Gradle Plugin与Gradle版本、JDK版本对应关系 配置示例 常见err 主要原因 1.编译版本未设定 2.有多个module而且gradle 版本设置不一致 修改如下&#xf…

虚幻闪烁灯光材质

创建一个材质 材质域改成光照函数 , Time让材质动起来 参数B用来控制速度 , Sine 让灯光闪烁 , Frac 增加了闪烁细节 把材质放到灯光材质上 效果还是挺不错的! 可以用于一些恐怖游戏~

OpenCV高级图形用户界面(8)在指定的窗口中显示一幅图像函数imshow()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在指定的窗口中显示一幅图像。 函数 imshow 在指定的窗口中显示一幅图像。如果窗口是以 cv::WINDOW_AUTOSIZE 标志创建的&#xff0c;图像将以原…

仕考网:国考笔试没进面还有机会吗?

在国家公务员考试及各省公务员考试中&#xff0c;除了常规的招录程序之外&#xff0c;还有调剂、递补和补录多重机会。 调剂&#xff1a;于笔试结束之后至面试启动之前.针对因报名人数不足未达到预定面试比例的岗位&#xff0c;将开放公开调剂。只要考生的笔试成绩超越了国考设…

如何查看默认网关地址:详细步骤

在日常的网络配置与故障排查中&#xff0c;了解并正确查看默认网关地址是一项基础且至关重要的技能。默认网关是连接本地网络与外部网络&#xff08;如互联网&#xff09;的关键节点&#xff0c;它扮演着数据包转发的重要角色。无论是家庭网络、办公室网络还是更复杂的网络环境…

一些简单的编程题(Java与C语言)

引言&#xff1a; 这篇文章呢&#xff0c;小编将会举一些简单的编程题用来帮助大家理解一下Java代码&#xff0c;并且与C语言做个对比&#xff0c;不过这篇文章所出现的题目小编不会向随缘解题系列里面那样详细的讲解每一到题&#xff0c;本篇文章的主要目的是帮助小编和读者们…

vcenter的使用

1 配置 1.1 时间配置 报错原因&#xff1a;ESXI主机没有配置DNS无法解析NTP服务器网址。 解决办法&#xff1a;配置ESXI主机DNS&#xff0c;操作如下图。 点击【配置】、【服务】 【编辑启动策略】 我们可以看到当前的【NTP服务状态】处于 已停止的状态 点击【配置】、【时间…

基于直播美颜SDK的实时美颜平台开发指南

随着直播平台的快速发展&#xff0c;用户对视频质量的要求越来越高&#xff0c;尤其是对于美颜效果的需求。为满足这一市场需求&#xff0c;基于直播美颜SDK的实时美颜平台应运而生。本文将探讨如何开发这样一个平台&#xff0c;助力开发者在激烈的竞争中脱颖而出。 一、理解美…

C#学习笔记(三)

C#学习笔记&#xff08;三&#xff09; 第 二 章 命名空间和类、数据类型、变量和代码规范二、类的组成和使用分析1. 基本概念2. 类的内容组成3. 方法的初步理解 第 二 章 命名空间和类、数据类型、变量和代码规范 二、类的组成和使用分析 1. 基本概念 类是程序的基本单元&a…

OpenCV高级图形用户界面(6)获取指定窗口中图像的矩形区域函数getWindowImageRect()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 提供窗口中图像的矩形区域。 该函数 getWindowImageRect 返回图像渲染区域的客户端屏幕坐标、宽度和高度。 函数原型 Rect cv::getWindowImage…

STM32_实验1_建立新工程

1、使用STM32CubeIDE建立一个新工程 1.1选择时钟源为外部晶振时钟。 1.2选择调试方式为 serial wire&#xff08;串行线&#xff09;。 1.3配置时钟树. 1.4选择以 c 和 h 文件型式管理工程文件。 1.5生成 hex 可执行文件。&#xff08;完成后点击锤子&#xff09; 2.串口输出调…