题目地址:https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable

题目描述

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

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

给你一个数组 edges ,其中 edges[i] = [typei, ui, vi] 表示节点 uivi 之间存在类型为 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. 1 <= n <= 10^5
  2. 1 <= edges.length <= min(10^5, 3 * n * (n-1) / 2)
  3. edges[i].length == 3
  4. 1 <= edges[i][0] <= 3
  5. 1 <= edges[i][1] < edges[i][2] <= n
  6. 所有元组 (typei, ui, vi) 互不相同

题目大意

删除最多的边,让两个人最终都能遍历全图。

解题思路

并查集

题目要求最多删除多少条边之后,两人都能完全遍历该图,换句话说,是要保证最终整个图对两个人都是连通的。

我们先讨论简单的情况,假设只有一种类型的边并且只有 1 个人,这种情况下最多删除图中的多少条边,仍然能让此人完全遍历这个图呢?

连通区域的问题,一般都可以使用 并查集 解决。并查集分为 “并”“查” 两部分。“并” 的部分,表示让两个区域连通;“查” 的部分,表示检查两个区域是否连通。本文不详细讲解并查集,但是会在代码部分,分享一个常用的并查集的代码模板。

我们需要遍历每一条边,判断这条边的两个顶点所在区域是否连通(利用了并查集的“查”的功能)。如果两个区域已经连通,说明该边无效,则抛弃该边;否则,说明这条边连通了两个未连通的区域,需要保留该边,且连通这两个区域(利用了并查集的“并”的功能)。

由于本题有两人,所以需要对 Alice 和 Bob 两人分别建一个并查集。我们仍然需要遍历每一条边,由于每个边是有类型的,因此需要根据这条边类型,确定是使用 Alice 的并查集还是 Bob 的并查集。

  • 类型 1:只能由 Alice 遍历,故使用 Alice 的并查集。
  • 类型 2:只能由 Bob 遍历,故使用 Bob 的并查集。
  • 类型 3:Alice 和 Bob 都可以遍历,故使用 Alice 和 Bob 两个人的并查集。

类型 3 的边可以同时连通 Alice 和 Bob 两个人的区域,一条边可以抵得上类型 1 和类型 2 两条边。题目要求最多可以删除多少条边,也就是说最终的图中应该保留最少的边,因此我们想到可以优先保留类型 3 的边。这种策略叫做“贪心”。

至此,本题的解题方法已经清楚了:

  1. 对 Alice 和 Bob 两人分别建一个并查集;

  2. 遍历所有类型 3 的边,分别检查 Alice 和 Bob 的两个并查集,判断此边的两个顶点所在区域是否连通,若不连通则使其连通;若已连通,则可以删除该边;

  3. 遍历所有类型 1 和类型 2 的边,如果是类型 1 则检查 Alice 的并查集,如果是类型 2 则检查 Bob 的并查集,判断此边的两个顶点所在区域是否连通,若不连通则使其连通;若已连通,则可以删除该边。

  4. 判断两个并查集的最终连通区域数是否都为 1。如果都为 1, 说明最终两人的图都是连通的,返回删除了多少边;否则,说明至少一人的图不连通,返回-1.

代码

先分享通用的并查集的模板。来自负雪明烛的博客「代码模板,刷题必会」,地址 https://fuxuemingzhu.blog.csdn.net/article/details/101900729

class DSU:
def __init__(self):
self.par = range(10001)

def find(self, x):
if x != self.par[x]:
self.par[x] = self.find(self.par[x])
return self.par[x] def union(self, x, y):
self.par[self.find(x)] = self.find(y) def same(self, x, y):
return self.find(x) == self.find(y)

对于本题而言,需要改造 union() 函数:如果此边属于同一个区域,那么应该删除此边,返回 1;如果此边属于不同的区域,则此边成功连通了两个区域,返回 0。这样,我们就可以直接对 union() 函数的返回结果求和,统计最终删除了多少条边。

本题的 Python 代码如下:

class Solution(object):
def maxNumEdgesToRemove(self, n, edges):
A = DSU(n)
B = DSU(n)
res = 0
for edge in edges:
if edge[0] != 3:
continue
res += A.union(edge[1], edge[2])
# 这里的结果只用加1次,因为只是1条边
B.union(edge[1], edge[2])
for edge in edges:
if edge[0] == 3:
continue
cur = A if edge[0] == 1 else B
res += cur.union(edge[1], edge[2])
return res if (A.regions() == 1 and B.regions() == 1) else -1 class DSU():
def __init__(self, n):
self.par_ = range(n + 1)
self.regions_ = n

def find(self, x):
if x != self.par_[x]:
self.par_[x] = self.find(self.par_[x])
return self.par_[x] def union(self, x, y):
px = self.find(x)
py = self.find(y)
if px == py:
return 1
self.par_[px] = py
self.regions_ -= 1
return 0 def regions(self):
return self.regions_

参考资料:

  1. 力扣(LeetCode),https://leetcode-cn.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable

  2. 花花酱:https://www.bilibili.com/video/BV1PZ4y1N78t

欢迎加入组织

算法每日一题是个互相帮助、互相监督的力扣打卡网站,其地址是 https://www.ojeveryday.com/

想加入千人刷题群的朋友,可以复制上面的链接到浏览器,然后在左侧点击“加入组织”,提交力扣个人主页,即可进入刷题群。期待你早日加入。

公众号:每日算法题

日期

2021 年 1 月 27 日 —— 日更公众号的第3天

【LeetCode】1579. 保证图可完全遍历 Remove Max Number of Edges to Keep Graph Fully Traversable的更多相关文章

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

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

  2. PTA 邻接表存储图的广度优先遍历(20 分)

    6-2 邻接表存储图的广度优先遍历(20 分) 试实现邻接表存储图的广度优先遍历. 函数接口定义: void BFS ( LGraph Graph, Vertex S, void (*Visit)(V ...

  3. leetcode解题报告(2):Remove Duplicates from Sorted ArrayII

    描述 Follow up for "Remove Duplicates": What if duplicates are allowed at most twice? For ex ...

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

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

  5. 图的深度优先遍历DFS

    图的深度优先遍历是树的前序遍历的应用,其实就是一个递归的过程,我们人为的规定一种条件,或者说一种继续遍历下去的判断条件,只要满足我们定义的这种条件,我们就遍历下去,当然,走过的节点必须记录下来,当条件 ...

  6. 图的深度优先遍历(DFS) c++ 非递归实现

    深搜算法对于程序员来讲是必会的基础,不仅要会,更要熟练.ACM竞赛中,深搜也牢牢占据着很重要的一部分.本文用显式栈(非递归)实现了图的深度优先遍历,希望大家可以相互学习. 栈实现的基本思路是将一个节点 ...

  7. C语言实现邻接矩阵创建无向图&图的深度优先遍历

    /* '邻接矩阵' 实现无向图的创建.深度优先遍历*/ #include <stdio.h> #include <stdlib.h> #define MaxVex 100 // ...

  8. 图的深度优先遍历(DFS)—递归算法

    实验环境:win10, DEV C++5.11 实验要求: 实现图的深度优先遍历 实验代码: #include <iostream> #define maxSize 255 #includ ...

  9. 数据结构与算法之PHP用邻接表、邻接矩阵实现图的广度优先遍历(BFS)

    一.基本思想 1)从图中的某个顶点V出发访问并记录: 2)依次访问V的所有邻接顶点: 3)分别从这些邻接点出发,依次访问它们的未被访问过的邻接点,直到图中所有已被访问过的顶点的邻接点都被访问到. 4) ...

随机推荐

  1. 【基因组组装】HiC挂载软件以及如何用Juice_box手工纠错?

    目录 1.常用HiC挂载软件 2. Juice_box手工纠错 1.常用HiC挂载软件 ALLHiC 张兴坦老师专为多倍体和高杂合度物种基因组挂载开发.如果是复杂基因组,肯定是首选.对于简单基因组,我 ...

  2. R包 tidyverse 分列

    代码: 1 library(tidyverse) 2 separate(data = df,col=chr_pos,into=c("chr","pos"),se ...

  3. Requests的安装和使用

    一.Requests的安装1.pip3 install requests2.验证 import requests 不报错即可

  4. WebRTC本地分享屏幕,录制屏幕

    WebRTC有分享屏幕的功能.使用的是getDisplayMedia方法.用户同意分享屏幕后,可以拿到视频流. 再结合MediaRecorder和Blob,把视频流数据存下来,就能得到录制屏幕的视频. ...

  5. 虚拟节点轻松应对 LOL S11 百万并发流量——腾竞体育的弹性容器实践

    作者 刘如梦,腾竞体育研发工程师,擅长高并发.微服务治理.DevOps,主要负责电竞服务平台架构设计和基础设施建设. 詹雪娇,腾讯云弹性容器服务EKS产品经理,主要负责 EKS 虚拟节点.容器实例相关 ...

  6. flink-----实时项目---day07-----1.Flink的checkpoint原理分析 2. 自定义两阶段提交sink(MySQL) 3 将数据写入Hbase(使用幂等性结合at least Once实现精确一次性语义) 4 ProtoBuf

    1.Flink中exactly once实现原理分析 生产者从kafka拉取数据以及消费者往kafka写数据都需要保证exactly once.目前flink中支持exactly once的sourc ...

  7. Web安全学习二

    目录 常见漏洞攻防 SQL注入 注入分类 按技巧分类 按获取数据的方式分类 注入检测 权限提升 数据库检测 绕过技巧 CheatSheet SQL Server Payload MySQL Paylo ...

  8. Shell学习(五)—— awk命令详解

    一.awk简介   awk是一个非常好用的数据处理工具,相对于sed常常作用于一整个行的处理,awk则比较倾向于一行当中分成数个[字段]处理,因此,awk相当适合处理小型的数据数据处理.awk是一种报 ...

  9. 如何将List集合中相同属性的对象合并

    在实际的业务处理中,我们经常会碰到需要合并同一个集合内相同属性对象的情况,比如,同一个用户短时间内下的订单,我们需要将各个订单的金额合并成一个总金额.那么用lambda表达式和HashMap怎么分别处 ...

  10. cordova配置与开发

    1.环境配置 1.1.安装ant 从 apache官网 下载ant,安装并配置,将ant.bat所在目录加到path环境变量,如c:\apache-ant\bin\.在cmd中运行以下语句如不报错即可 ...