一、题目内容

Alice 和 Bob 共有一个无向图,其中包含 n 个节点和 3  种类型的边:

  • 类型 1:只能由 Alice 遍历。
  • 类型 2:只能由 Bob 遍历。
  • 类型 3:Alice 和 Bob 都可以遍历。

给你一个数组 edges ,其中 edges[i] = [typei, ui, vi] 表示节点 ui 和 vi 之间存在类型为 typei 的双向边。请你在保证图仍能够被 Alice和 Bob 完全遍历的前提下,找出可以删除的最大边数。如果从任何节点开始,Alice 和 Bob 都可以到达所有其他节点,则认为图是可以完全遍历的。

返回可以删除的最大边数,如果 Alice 和 Bob 无法完全遍历图,则返回 -1 。

示例 1:

输入:n = 4, edges = [[3,1,2],[3,2,3],[1,1,3],[1,2,4],[1,1,2],[2,3,4]]
输出:2
解释:如果删除 [1,1,2] 和 [1,1,3] 这两条边,Alice 和 Bob 仍然可以完全遍历这个图。再删除任何其他的边都无法保证图可以完全遍历。所以可以删除的最大边数是 2 。

示例 2:

输入:n = 4, edges = [[3,1,2],[3,2,3],[1,1,4],[2,1,4]]
输出:0
解释:注意,删除任何一条边都会使 Alice 和 Bob 无法完全遍历这个图。

示例 3:

输入:n = 4, edges = [[3,2,3],[1,1,2],[2,3,4]]
输出:-1
解释:在当前图中,Alice 无法从其他节点到达节点 4 。类似地,Bob 也不能达到节点 1 。因此,图无法完全遍历。

提示:

1 <= n <= 10^5
1 <= edges.length <= min(10^5, 3 * n * (n-1) / 2)
edges[i].length == 3
1 <= edges[i][0] <= 3
1 <= edges[i][1] < edges[i][2] <= n
所有元组 (typei, ui, vi) 互不相同

二、解题思路

维护三种线段的连通关系,线段3一般要保留,毕竟是公用的。

具体思路看代码注释。

三、代码

class Solution:def maxNumEdgesToRemove(self, n: int, edges: list) -> int:uf1 = UnionFind(n)uf2 = UnionFind(n)uf3 = UnionFind(n)count1 = 0  # 线段1的个数count2 = 0  # 线段2的个数count3 = 0  # 线段3的个数redundant_count3 = 0  # 线段3冗余的个数for i in range(len(edges)):edge_type = edges[i][0]  # 线段种类st = edges[i][1] - 1ed = edges[i][2] - 1# 记录每种线段的个数if edge_type == 1:count1 += 1elif edge_type == 2:count2 += 1elif edge_type == 3:count3 += 1else:raise ValueError# 每种线段进行连通if edge_type == 1 or edge_type == 3:uf1.Union(st, ed)if edge_type == 2 or edge_type == 3:uf2.Union(st, ed)if edge_type == 3:if not uf3.isConnected(st, ed):uf3.Union(st, ed)else:# 已经连通说明冗余redundant_count3 += 1# 线段3直接连通了所有点if uf3.getCount() == 1:return count1 + count2 + redundant_count3  # 删除的边可以是线段1+线段2+线段3冗余的个数# 线段1和线段2同时连通, 那么都可以走的路不需要删除,也就是线段3不需要删除,但是要删除线段3的冗余if uf1.getCount() == 1 and uf2.getCount() == 1:return count1 - (uf3.getCount() - 1) + \count2 - (uf3.getCount() - 1) + redundant_count3return -1class UnionFind:def __init__(self, n):self.count = nself.root = [0 for _ in range(n)]self.size = [0 for _ in range(n)]for i in range(n):self.root[i] = iself.size[i] = idef find(self, x):if x != self.root[x]:self.root[x] = self.find(self.root[x])return self.root[x]else:return xdef isConnected(self, x, y):return self.find(x) == self.find(y)def getCount(self):return self.countdef Union(self, x, y):# 查找x和y的根/父节点rx = self.find(x)ry = self.find(y)# 根/父节点相同, 说明已经连通了if rx == ry:return  # 直接返回if self.size[rx] < self.size[ry]:self.root[rx] = ryself.size[ry] += self.size[rx]else:self.root[ry] = rxself.size[rx] += self.size[ry]self.count -= 1if __name__ == '__main__':s = Solution()n = 4edges = [[3, 1, 2],[3, 2, 3],[1, 1, 3],[1, 2, 4],[1, 1, 2],[2, 3, 4]]ans = s.maxNumEdgesToRemove(n, edges)print(ans)

leetcode_1579. 保证图可完全遍历相关推荐

  1. leetcode 1579. 保证图可完全遍历(并查集)

    Alice 和 Bob 共有一个无向图,其中包含 n 个节点和 3 种类型的边: 类型 1:只能由 Alice 遍历. 类型 2:只能由 Bob 遍历. 类型 3:Alice 和 Bob 都可以遍历. ...

  2. 力扣题解-1579. 保证图可完全遍历(并查集)

    题目:1579. 保证图可完全遍历 Alice 和 Bob 共有一个无向图,其中包含 n 个节点和 3 种类型的边: 类型 1:只能由 Alice 遍历. 类型 2:只能由 Bob 遍历. 类型 3: ...

  3. 并查集之LeetCode1579. 保证图可完全遍历

    并查集之LeetCode1579. 保证图可完全遍历 前言 一,1579. 保证图可完全遍历 二,解题思路 三, 代码 总结 前言 算法之并查集 一,1579. 保证图可完全遍历 Alice 和 Bo ...

  4. 1579. 保证图可完全遍历

    链接:1579. 保证图可完全遍历 题解: https://www.bilibili.com/video/BV1PZ4y1N78t 1.贪心算法:先通过3类型的边,构成a和b的并查集.因为类型3的边, ...

  5. 每日一题:leetcode1579.保证图可完全遍历

    题目描述 题目分析 非常惭愧,感觉自己有点畏难心理,看到是困难题第一个想法是自己想不出来... 因为自己认为自己做不出来,所以完全不能进行思考,稍微思考一下就觉得不行不行. 我也想到了分别用两个并查集 ...

  6. 邻接表存储图的广度优先遍历

    试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(Vertex) ); 其中LGraph是邻接表存储 ...

  7. 数据结构与算法:终于可以用三种语言(C,C#,JavaScript)把图的广度优先遍历讲清楚了(推荐收藏)

    文章目录 邻接矩阵存储图的广度优先遍历过程分析 C语言实现队列编程 程序中加入图的处理函数 结果的再次分析 C#语言实现图的广度优先遍历.并显示广度优先遍历生成树 JavaScript语言实现图的广度 ...

  8. 邻接矩阵存储图的深度优先遍历

    练习6.1 邻接矩阵存储图的深度优先遍历 (20 分) 试实现邻接矩阵存储图的深度优先遍历. 函数接口定义: void DFS( MGraph Graph, Vertex V, void (*Visi ...

  9. 超详细C语言版数据结构:图的深度优先遍历(推荐收藏)

    文章目录 一.邻接矩阵存储图的深度优先遍历过程分析 二.结果分析 三.C语言编程实现图的深度优先遍历 四.图的遍历及其应用 一.邻接矩阵存储图的深度优先遍历过程分析 对图1这样的无向图,要写成邻接矩阵 ...

最新文章

  1. python猿辅导_如何用数据分析方法剖析“猿辅导”K12课程
  2. try/catch的用法
  3. golang goroutine 得到返回值
  4. vim配置@year12
  5. 我是如何用 Redis 做实时订阅推送的?
  6. 利用SQL05特性删除表中重复数据
  7. 计算机电子琴弹奏怎么打开,怎么打开电脑键盘电子琴软件
  8. 哪个内存更快?Heap或ByteBuffer或Direct?
  9. unity打光报错:Mesh doesnt have albedo UVs,Please creat them in your modelling package
  10. DVWA系列之10 命令执行漏洞的挖掘与防御
  11. 微软visio2013安装问题及解决过程
  12. mac打不开磁盘映像资源忙
  13. 活动运营中如何准确把握用户心理
  14. 儿时的生活还记得吗?
  15. tophat 原理_Tophat2比对原理及命令
  16. 【读官方文档,学原味技术】SpringBoot-Staters和自定义Starter
  17. 夜间车尾灯检测的方法
  18. 【java毕业设计】基于java+Eclipse +SQL Server的工厂进销存管理系统设计与实现(毕业论文+程序源码)——工厂进销存管理系统
  19. 干货 | 研发测试管理是测试能力的基础
  20. C语言+windows API仿写类酷狗播放器(1)

热门文章

  1. 成考高起专计算机统考试题,2018年成人高考高起专英语考试试题及答案
  2. C#调用百度api,根据经度和纬度获取地理位置信息
  3. 有关TN-C、TN-S和TN-C-S三种系统
  4. 3. 使用DSPack打开摄像头
  5. android editext下拉框,android实现下拉框和输入框结合
  6. 使用Socks5代理下载Android源码
  7. 通过CSS实现奥运五环效果、实现环环相扣效果
  8. 数字文明时代需要更好的GDP
  9. goland如何去除注释中的下划波浪线
  10. 「超强」ChatGPT撰写的软件定制开发行业可行性报告分析