【LeetCode】1697. 检查边长度限制的路径是否存在

news2024/11/25 16:28:48

题目描述

给你一个 n 个点组成的无向图边集 edgeList ,其中 edgeList[i] = [ui, vi, disi] 表示点 ui 和点 vi 之间有一条长度为 disi 的边。请注意,两个点之间可能有 超过一条边 。
给你一个查询数组queries ,其中 queries[j] = [pj, qj, limitj] ,你的任务是对于每个查询 queries[j] ,判断是否存在从 pj 到 qj 的路径,且这条路径上的每一条边都 严格小于 limitj
请你返回一个 布尔数组 answer ,其中 answer.length == queries.length ,当 queries[j] 的查询结果为 true 时, answer 第 j 个值为 true ,否则为 false 。

示例 1:

输入:n = 3, edgeList = [[0,1,2],[1,2,4],[2,0,8],[1,0,16]], queries = [[0,1,2],[0,2,5]]
输出:[false,true]
在这里插入图片描述
解释:上图为给定的输入数据。注意到 0 和 1 之间有两条重边,分别为 2 和 16 。
对于第一个查询,0 和 1 之间没有小于 2 的边,所以我们返回 false 。
对于第二个查询,有一条路径(0 -> 1 -> 2)两条边都小于 5 ,所以这个查询我们返回 true 。

示例 2:

输入:n = 5, edgeList = [[0,1,10],[1,2,5],[2,3,9],[3,4,13]], queries = [[0,4,14],[1,4,13]]
输出:[true,false]
在这里插入图片描述
解释:上图为给定数据。

提示:

2 <= n <= 105
1 <= edgeList.length, queries.length <= 105
edgeList[i].length == 3
queries[j].length == 3
0 <= ui, vi, pj, qj <= n - 1
ui!= vi
pj != qj
1 <= disi, limitj <= 109
两个点之间可能有 多条 边。

方法一:并查集+离线思维

思路:

  • 将 queries 按照 limitj 从小到大进行排序,这样所有的询问中对边权的限制就 单调递增 了;
  • 同时,将 edgeList 按照 disj 从小到大排序,这样所有的边权也就 单调递增 了;
  • 使用 并查集 维护图的连通性,并使用指针 i 表示当前并查集中添加的最后一条边;
  • 当我们处理到询问 queriesj = (pj , qj, limitj) 时,由于 limitj 单调递增,因此只需要往并查集中添加新的边,即不断地在 edgeList 中向右移动指针 i ,直到当前指向的边权 disi >= limitj 为止;
  • 随后只需要使用并查集判断 pj 和 qj 是否连通即可。

情况

  • 通过;

收获

  • 这道题看了一下感觉会用到的知识,这一块我很薄弱,就直接看题解了,没想到比图还更难;
  • 离线思维
    对于一道题目会给出若干询问,而这些询问是全部提前给出的,也就是说,不必按照询问的顺序依次对它们进行处理,而是可以按照某种顺序或者把所有询问看成一个整体处理。
  • 并查集
    一种树形的数据结构,用于处理集合的合并和查询问题,支持两种操作:
    • 查找(Find):确定某个元素处于哪个子集;该操作会用到路径压缩。
    • 合并(Union):将两个子集合并成一个集合;

代码中包含并查集模板

  • 将 queries 和 edgeList 进行排序的巧妙之处,在于我们实际上进行了这样的操作:
    • 将所有的 queries 和 edgeList 合并,并按照边权或者边权限制进行排序。在出现相等的情况时, queries 或者 edgeList 内部的相对顺序并不重要,但所有的 queries 必须要排在所有的 edgeList 之前,这是因为题目中要求对于每一个询问,经过的边权都是严格小于边权限制的;
  • 在排序之后,我们依次遍历所有元素。如果当前元素是 queries ,我们就使用并查集进行查询操作,如果当前元素是 edgeList ,就使用并查集进行修改操作。
  • 对下标数组进行排序
    这一题中没有直接对 queries 进行排序,因为如果这么做会导致答案数组和 queries 的原来顺序对不上。因此使用 iota 函数(自加函数) 生成一个从 0 开始的 下标数组 ,对 qid下标数组进行排序,使得顺序取 qid 数组的值作为下标来访问 queries 数组,就是对 queries 数组的升序访问。
    这一种方法适用于 对答案有特殊顺序要求 或 不方便对原来数组直接进行排序 的情况。

时间复杂度:O(m logm + q logq),其中 m 和 q 分别是数组 edgeList 和 queries 的长度,时间复杂度的瓶颈在于排序;
空间复杂度:O(n + logm + q),其中O(n) 为并查集, O(logm)为数组 edgeList 排序使用的栈空间,O(q)为存储所有询问的编号,对应排序中O(logq)的栈空间,可以忽略。

// 并查集模板,包含路径压缩以及按秩合并
class UF{
public:
    vector<int> fa; // 存储每个点的父节点,初始时每个点的父节点都是它本身
    vector<int> sz; // 只有节点是祖宗节点时才有意义,表示祖宗节点所在集合中点的数量
    int n; // 节点数
    int comp_cnt; 

public:
    // 有参数的构造函数
    UF(int _n): n(_n), comp_cnt(_n), fa(_n), sz(_n, 1){ 
        // iota:自增函数,fa=[0,1,2,3,...]
        iota(fa.begin(), fa.end(), 0);
    }

    // 寻找元素x的集合的祖宗节点
    int findset(int x){
        return fa[x] == x ? x : fa[x] = findset(fa[x]);
        // 路径压缩:
        // fa[x] = findset(fa[x])
    }

    bool unite(int x, int y){
        x = findset(x);
        y = findset(y);
        if(x == y){
            // 两个元素在同一个集合中,无需合并
            return false;
        }

        // 合并x和y
        // 确保x是秩大的元素
        if(sz[x] < sz[y]){
            swap(x, y);
        }
        fa[y] = x; // 将y加入集合x
        sz[x] += sz[y]; // 更新x的秩
        -- comp_cnt;
        return true;
    }

    // 判断x和y是否连通
    bool connected(int x, int y){
        x = findset(x);
        y = findset(y);
        // 如果x和y在一个集合中,表示连通
        return x == y; 
    }
};
class Solution{
public:
    vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& edgeList, vector<vector<int>>& queries) {
        vector<int> qid(queries.size());
        // 创建0 - (n-1) 的数组
        iota(qid.begin(), qid.end(), 0); 
        // 将queries按照边权限制从小到大排序 
        // [&]:以引用形式捕获所有外部变量,也就是外部变量均可用
        sort(qid.begin(), qid.end(), [&](int i, int j){
            return queries[i][2] < queries[j][2];
        });

        // 将edgeList按照从小到大排序
        sort(edgeList.begin(), edgeList.end(), [](const auto& e1, const auto& e2){
            return e1[2] < e2[2];
        });

        // 并查集
        UF uf(n);

        int i = 0;
        vector<bool> ans(queries.size());
        for(int query : qid){
            // 往并查集中添加元素,直到边权关系 dis_i < limit_j 不满足
            while(i < edgeList.size() && edgeList[i][2] < queries[query][2]){
                uf.unite(edgeList[i][0], edgeList[i][1]);
                ++ i;
            }
            // 使用并查集判断连通性
            ans[query] = uf.connected(queries[query][0], queries[query][1]);
        }
        return ans;
    }
};

参考资料

  1. c++ iota()函数

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

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

相关文章

外部注意力机制与内部注意力机制

自注意力是注意力机制的一种特殊情况&#xff0c;其核心思想为通过计算特征内部元素之间的联系来获得大范围内的依赖关系。而在外部注意力中&#xff0c;key被拿到了网络外部&#xff0c;因此可以习得数据集的全局状况。 自注意力机制中&#xff0c;输入特征F被投射到query矩阵…

Qt扫盲-QAbstractSlider理论总结

QAbstractSlider理论总结1. 概述2. 常用属性3. 信号1. 概述 QAbstractSlider 其实就是 QScrollBar, QSlider and QDial 的父类&#xff0c;也就是抽象类定义了Slider这种控件的一些公共属性&#xff0c;其实就是一个抽象滚动条的主要属性。 就比如一个具体的滑动条&#xff0c…

服务器load高问题定位和优化

服务器开发系列 文章目录服务器开发系列前言一、原因分析与定位&#xff1f;总结前言 什么是Load&#xff1f;什么是Load Average?   Load 就是对计算机干活多少的度量&#xff08;WikiPedia&#xff1a;the system Load is a measure of the amount of work that a comput…

isaac gym(二)仿真setup(代码齐全)

目录 .1 Simulation Setup .2 Creating a Simulation 2.1 Simulation Parameters 2.1.1 Up Axis 2.2 Creating a Ground Plane .3 Loading Assets .4 Environments and Actors 4.1 env 4.2 actors 4.3 Test .5 Running the Simulation .6 Adding a Viewer ​编辑 .7 Th…

03_1排序算法:冒泡排序、选择排序、插入排序

开始系统学习算法啦&#xff01;为后面力扣和蓝桥杯的刷题做准备&#xff01;这个专栏将记录自己学习算法是的笔记&#xff0c;包括概念&#xff0c;算法运行过程&#xff0c;以及代码实现&#xff0c;希望能给大家带来帮助&#xff0c;感兴趣的小伙伴欢迎评论区留言或者私信博…

专访 | 刘乔升:开源是人类智力劳动最好的组织形式

OpenMLDB&#xff1a; 可以请你先自我介绍一下吗&#xff1f; 刘乔升&#xff1a; 我叫刘乔升&#xff0c;来自复旦大学&#xff0c;就读于软件工程专业&#xff0c;是 2022 开源之夏 OpenMLDB Go SDK 项目的贡献者。在参加本届开源之夏活动前&#xff0c;我就有参加过一些开源…

自定义maven骨架

目录 一、自定义maven骨架 1、先创建一个新的工程、添加你需要的结构目录及pom所需要的依赖文件&#xff0c;以这个工程为模板&#xff0c;创建框架 2、添加在pom文件中添加依赖&#xff0c;com.test文件中这个坐标与maven仓库相对应 3、点击Edit....会有一个弹窗 4、点击加…

如何在SpringBoot中设置HTTP缓存,你知道么?

在工作之余阅读缓存相关的书籍时&#xff0c;看到了http缓存相关的知识&#xff0c;HTTP 缓存机制是一个 web 性能优化的重要手段&#xff0c;无论是做前端还是做web后台&#xff0c;都可能会用得到它&#xff0c;应该是知识体系库中的一个基础环节&#xff0c;以前这一块学的不…

TAPD新增需求自动写入腾讯文档

【实现效果&#xff1a;】TAPD新增需求/缺陷&#xff0c;可以自动写入腾讯文档智能表&#xff0c;方便通过腾讯文档灵活管理自己的项目排期&#xff0c;并且通过不同的视图效果&#xff0c;实现简单的需求统计/分组迭代&#xff0c;通过数据关联及时跟进延期项目。 【准备工作…

引用类型 - JavaScript 数组对象、遍历、复制、冒泡排序、选择排序、数组方法、数组去重

写在前面 哎呀呀&#xff0c;每次都是要沉淀好久好久才能更一篇文章…基本上半个月都很难出一篇&#xff0c;但还是想把这个系列做起来&#xff0c;主要是为了记录自己学习和开发的过程&#xff0c;以便在面试的时候讲项目&#xff0c;能说得头头是道(◍•ᴗ•◍) 马上就要开…

Clickhouse

目录 Clickhouse简介 整体架构 数据接入层 数据存储层 数据服务层 数据应用层 Clickhouse简介 目前企业用户行为日志每天百亿量级&#xff0c;虽然经过数仓的分层以及数据汇总层通用维度指标的预计算&#xff0c;有些个性化的分析场景还是需要直接编写程序或sql查询&…

python人工智能学习需要学什么?

前言 如果要从科技领域找出最大的变化和革新&#xff0c;那么我们很难不说到“人工智能”这个关键词。人工智能催生了大量新技术、新企业和新业态&#xff0c;为个人、企业、国家乃至全球提供了新的经济增长点&#xff0c;上到谷歌、苹果、百度等巨头&#xff0c;下到各类创业…

发布-订阅模式解读

发布-订阅模式 先简单说一下发布订阅模式各个组件的定义: 发布者 Publisher : 状态改变时 , 向 消息中心 发送事件 ; 订阅者 Subscriber : 到 消息中心 订阅自己关心的事件 ; 消息中心 : 负责维护一个 消息队列 , 根据 消息类型 将 消息 转发给 对应的 订阅者 ; 下面按照该…

差错控制方法----循环冗余码计算

差错控制方法----循环冗余码计算 循环冗余码&#xff0c;又称为多项式码。CRC的工作方法是在发送端产生一个冗余码&#xff0c;附加在信息位后面一起发送到接收端&#xff0c;接收端收到的信息按发送端形成循环冗余码同样的算法进行校验&#xff0c;如果发现错误&#xff0c;则…

(附源码)php校园电子图像信息采集系统 毕业设计 010930

目 录 摘要 1 1 绪论 1 1.1 研究背景 1 1.2研究内容 1 1.3论文结构与章节安排 1 2 校园电子图像信息采集系统 系统分析 3 2.1 可行性分析 3 2.2 系统流程分析 3 2.2.1 数据增加流程 3 2.2.2 数据修改流程 4 2.3.3数据删除流程 4 2.3 系统功能分析 4 2.3.1 功能性分析 4 2.3.2 …

多态——C++第三大特性

目录 一、多态的概念 1、概念 二、多态的定义及实现 1、构成条件 2、虚函数 3、虚函数的重写 4、C11提供了override和final两个关键字&#xff0c;可以帮助用户检测是否重写 5、重载、覆盖&#xff08;重写&#xff09;、隐藏&#xff08;重定义&#xff09;的对比 三、…

pytorch环境配置

pytorch环境配置pytorch环境配置1.NVIDIA驱动安装与更新1.查看自己的电脑显卡版本2.下载显卡驱动3.安装与验证2.pytorch环境安装1.打开anaconda的终端2. 创建虚拟环境3.换源4.安装5.验证3.pycharm项目的pytorch环境设置pytorch环境配置 使用Anacondapycharm搭建pytorch环境 提…

常见的四大搜索引擎区别

一般应用或网站的信息会存储在数据库中&#xff0c;而随着时间的推移&#xff0c;数据库中的信息量达到一个量级后会出现访问速度变慢的情况&#xff0c;例如用户在客户端搜索一个商品名称&#xff0c;系统可能加载了好几秒才显示数据&#xff0c;这个时候就需要进行一些优化处…

ET框架(三)

Model》数据 HotFix》行为 ET框架中的ECS和Unity的ECS无关 hotfix 静态类静态方法>行为 可以控制组件 Model》数据 继承Entity IAwake初始化 Scene实体的子实体类型 特殊&#xff1a; Unity.hotfixView : Unity相关的行为 Unity .modeView: Unity相关的数据 代码公用&a…

WSL_01 Windows WSL 安装并配置镜像与SSH

文章目录1 WSL介绍2 安装步骤2.1 启用适用于 Linux 的 Windows 子系统2.2 检查运行 WSL 2 的要求2.3 启用虚拟机功能2.4 下载 Linux 内核更新包2.5 将 WSL 2 设置为默认版本2.6 安装所选的Linux 分发解决无法打开微软商店2.6.1 配置网络2.6.2 使用官方教程的链接2.6.3 使用命令…