Leetcode743. 网络延迟时间

Every day a Leetcode

题目来源:743. 网络延迟时间

本题需要用到单源最短路径算法 Dijkstra,现在让我们回顾该算法,其主要思想是贪心。

将所有节点分成两类:已确定从起点到当前点的最短路长度的节点,以及未确定从起点到当前点的最短路长度的节点(下面简称「未确定节点」和「已确定节点」)。

每次从「未确定节点」中取一个与起点距离最短的点,将它归类为「已确定节点」,并用它「更新」从起点到其他所有「未确定节点」的距离。直到所有点都被归类为「已确定节点」。

用节点 A「更新」节点 B 的意思是,用起点到节点 A 的最短路长度加上从节点 A 到节点 B 的边的长度,去比较起点到节点 B 的最短路长度,如果前者小于后者,就用前者更新后者。这种操作也被叫做「松弛」。

这里暗含的信息是:每次选择「未确定节点」时,起点到它的最短路径的长度可以被确定。

可以这样理解,因为我们已经用了每一个「已确定节点」更新过了当前节点,无需再次更新(因为一个点不能多次到达)。而当前节点已经是所有「未确定节点」中与起点距离最短的点,不可能被其它「未确定节点」更新。所以当前节点可以被归类为「已确定节点」。

解法1:朴素 Dijkstra 算法

适用于稠密图。

代码:

/*
 * @lc app=leetcode.cn id=743 lang=cpp
 *
 * [743] 网络延迟时间
 */

// @lc code=start
class Solution
{
private:
    const int inf = INT_MAX / 2;

public:
    int networkDelayTime(vector<vector<int>> &times, int n, int k)
    {
        vector<vector<int>> g(n, vector<int>(n, inf));
        for (auto &time : times)
        {
            int u = time[0] - 1, v = time[1] - 1;
            int w = time[2];
            g[u][v] = w;
        }
        // dist[i] 表示点 k 到其他节点的最短距离
        vector<int> dist(n, inf);
        dist[k - 1] = 0;
        vector<int> used(n);
        for (int i = 0; i < n; i++)
        {
            int x = -1;
            for (int y = 0; y < n; y++)
                if (!used[y] && (x == -1 || dist[y] < dist[x]))
                    x = y;
            used[x] = true;
            for (int y = 0; y < n; y++)
                dist[y] = min(dist[y], dist[x] + g[x][y]);
        }

        int ans = *max_element(dist.begin(), dist.end());
        return ans == inf ? -1 : ans;
    }
};
// @lc code=end

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(n2+m),其中 n 是节点个数,m 是数组 times 的长度。

空间复杂度:O(n2),其中 n 是节点个数。

解法2:堆优化 Dijkstra 算法

适用于稀疏图。

寻找最小值的过程可以用一个最小堆来快速完成:

  • 一开始把 (dis[k],k) 二元组入堆。
  • 当节点 x 首次出堆时,dis[x] 就是写法一中寻找的最小最短路。
  • 更新 dis[y] 时,把 (dis[y],y) 二元组入堆。

注意,如果一个节点 x 在出堆前,其最短路长度 dis[x] 被多次更新,那么堆中会有多个重复的 x,并且包含 x 的二元组中的 dis[x] 是互不相同的(因为我们只在找到更小的最短路时才会把二元组入堆)。

所以写法一中的 used 数组可以省去,取而代之的是用出堆的最短路值(记作 dx)与当前的 dis[x] 比较,如果 dx>dis[x] 说明 x 之前出堆过,我们已经更新了 x 的邻居的最短路,所以这次就不用更新了,继续外层循环。

代码:

// 堆优化 Dijkstra(适用于稀疏图)

class Solution
{
private:
    const int inf = INT_MAX / 2;

public:
    int networkDelayTime(vector<vector<int>> &times, int n, int k)
    {
        vector<vector<pair<int, int>>> g(n); // 邻接表
        for (auto &time : times)
        {
            int u = time[0] - 1, v = time[1] - 1;
            int w = time[2];
            g[u].emplace_back(v, w);
        }
        // dist[i] 表示点 k 到其他节点的最短距离
        vector<int> dist(n, inf);
        dist[k - 1] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
        pq.emplace(0, k - 1);
        while (!pq.empty())
        {
            auto [dx, x] = pq.top();
            pq.pop();
            if (dx > dist[x])
            { // x 之前出堆过
                continue;
            }
            for (auto &[y, d] : g[x])
            {
                int new_dist = dx + d;
                if (new_dist < dist[y])
                {
                    dist[y] = new_dist; // 更新 x 的邻居的最短路
                    pq.emplace(new_dist, y);
                }
            }
        }

        int ans = *max_element(dist.begin(), dist.end());
        return ans == inf ? -1 : ans;
    }
};

结果:

在这里插入图片描述

复杂度分析:

时间复杂度:O(mlog⁡m),其中 m 是数组 times 的长度。值得注意的是,如果输入的是稠密图,本写法的时间复杂度为 O(n2log⁡n),不如写法一。

空间复杂度:O(m),其中 m 是数组 times 的长度。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

分类分析|KNN分类模型及其Python实现

KNN分类模型及其Python实现 1. KNN算法思想2. KNN算法步骤2.1 KNN主要优点2.2 KNN主要缺点 3. Python实现KNN分类算法3.1 自定义方法实现KNN分类3.2 调用scikit-learn模块实现KNN分类 4. K值的确定 在之前文章 分类分析|贝叶斯分类器及其Python实现中&#xff0c;我们对分类分…

DHCP的原理与配置

一.了解DHCP服务 1. DHCP (Dynamic Host Configuration Protocol)动态主机配置协议 是由Internet工作小组设计开发的&#xff0c;专门用于为TCP/IP网络中的计算机自动分配TCP/IP参数的协议 DHCP协议采用的是UDP作为传输协议&#xff0c;是给网络内的客户机自动分配IP地址&…

Redis入门到通关之Redis实现Session共享

文章目录 ☃️前期概要☃️基于Session实现登录方案☃️现有方案存在的问题☃️Redis代替Session的业务流程❄️❄️设计key的结构❄️❄️设计key的具体细节❄️❄️整体访问流程 欢迎来到 请回答1024 的博客 &#x1f353;&#x1f353;&#x1f353;欢迎来到 请回答1024的博…

羊大师分析,羊奶和牛奶哪个更适合夏天喝?

羊大师分析&#xff0c;羊奶和牛奶哪个更适合夏天喝&#xff1f; 羊奶和牛奶都是营养丰富的饮品&#xff0c;适合不同人群在不同季节饮用。在夏天&#xff0c;选择羊奶还是牛奶主要取决于个人的体质、口味偏好以及需求。 羊奶的营养价值较高&#xff0c;含有丰富的蛋白质、矿物…

ESP8266+STM32+阿里云保姆级教程(AT指令+MQTT)

前言&#xff1a;在开发过程中&#xff0c;几乎踩便了所有大坑小坑总结出的文章&#xff0c;我是把坑踩满了&#xff0c;帮助更过小白快速上手&#xff0c;如有错误之处&#xff0c;还麻烦各位大佬帮忙指正、 目录 一、ESP-01s介绍 1、ESP-01s管脚功能&#xff1a; 模组启动模…

元数据管理和数据目录对于现代数据平台的重要性——Lakehouse架构(四)

文章目录 前言解读元数据技术元数据业务元数据 元存储和数据目录如何协同工作&#xff1f;数据目录的特点查询、检索和发现数据数据分类数据治理数据血缘 前言 Lakehouse 架构中的存储层负责存储整个平台的数据&#xff0c;要查询存储的这些数据&#xff0c;我们需要一个数据目…

xgp怎么取消续费 微软商店xgp会员取消自动续费详细教程

xgp怎么取消续费 微软商店xgp会员取消自动续费详细教程 XGP这个游戏平台小伙伴们并不陌生吧&#xff0c;它是微软Xbox游戏部门推出的游戏租赁制会员服务&#xff0c;主要用于主机和PC两个平台。这个平台的会员就可以免费享受多款大制作游戏&#xff0c;而且每个月还会自动更新…

ruoyi-nbcio-plus基于vue3的flowable收回任务后重新进行提交表单的处理

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

JAVA毕业设计137—基于Java+Springboot+Vue的物流快递仓库管理系统(源代码+数据库)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的物流快递仓库管理系统(源代码数据库)137 一、系统介绍 本项目前后端分离&#xff0c;分为员工、销售员、仓库员、商品管理员、超级管理员五种角色 1、员工…

Linux 的情况下实现贪吃蛇 -- 第二十八天

1. 打印地图 keypad(stdsrc,1) 参数表示是否接收&#xff0c;1表示接收指令 2.思路&#xff1a;初始化initNcurses()&#xff0c; 封装地图函数实现地图gamePic&#xff08;&#xff09; 分三部分实现&#xff1a;2.1: 在第0行&#xff1a;打印 "--",&quo…

矩阵连乘算法

矩阵连乘&#xff1a; #include<iostream> #define inf 0x7fffffff using namespace std; int a[256] { 0 };//存储矩阵的行和列 int m[256][256] { 0 };//存储i到j的最少计算次数 int s[256][256] { 0 };//存储i到j的中转站k void m_print(int i, int j) {if (i …

javaWeb项目-房屋房租租赁系统功能介绍

项目关键技术 开发工具&#xff1a;IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架&#xff1a;ssm、Springboot 前端&#xff1a;Vue、ElementUI 关键技术&#xff1a;springboot、SSM、vue、MYSQL、MAVEN 数据库工具&#xff1a;Navicat、SQLyog 1、JSP技术 JSP(Jav…

数据结构-二叉树-链式

一、链式二叉树的结构 typedef int BTNodeDataType; typedef struct BTNode {BTNodeDataType data;struct BTNode* left;struct BTNode* right; }BTNode; 二叉树的前中后序遍历 前序&#xff1a;根左右 中序&#xff1a;左根右 后序&#xff1a;左右根 void PreOrder(BTNo…

栈 、队列

1.stack的介绍和使用 1.1stack的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 1.2 stack的使用 函数说明 接口说明 stack() 构造空的栈 empty() 检测stack是否为空 size…

Opencv | 边缘检测 轮廓信息

目录 一. 边缘检测1. 边缘的定义2. Sobel算子 边缘提取3. Scharr算子 边缘提取4. Laplacian算子 边缘提取5. Canny 边缘检测算法5.1 计算梯度的强度及方向5.2 非极大值抑制5.3 双阈值检测5.4 抑制孤立弱边缘 二. 轮廓信息1. 获取轮廓信息2. 画轮廓 一. 边缘检测 1. 边缘的定义…

【QT】Ubuntu22.04 配置 QT6.5 LTS

【QT】Ubuntu22.04 配置 QT6.5 LTS 文章目录 【QT】Ubuntu22.04 配置 QT6.5 LTS1.注册QT Group的账号2.安装QT Creator3.启动QT Creator报错from 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.4.运行QT的demoReference 1.注册QT Group的…

mysql buffer pool详解

介绍 缓冲池是InnoDB在访问表和索引数据时缓存的主内存区域。缓冲池允许直接从内存访问频繁使用的数据&#xff0c;这加快了处理速度。在专用服务器上&#xff0c;通常会将多达80%的物理内存分配给缓冲池。 为了提高大容量读操作的效率&#xff0c;缓冲池被划分为可能包含多行…

类与对象(三) 拷贝构造与赋值运算符重载

目录 1.拷贝构造 2.运算符重载&#xff08;日期类举例&#xff09; 1. 2.和 3. > > < < 4.赋值运算符重载 5.- 与- 6. -- 7.日期 - 日期 3.const成员函数 4.<<和>>重载 5.取地址重载 1.拷贝构造 拷贝构造也是一个构造函数。我们前…

Linux:动静态库介绍

动静态库 库的介绍开发环境 & 编译器库存在的意义库的实现库的命名静态库制作和使用总结 动态库的制作和使用动态库的使用方法方法一方法二方法三 库加载问题静态库加载问题动态库的加载问题与位置无关码 C/C静态库下载方式 库的介绍 静态库&#xff1a;程序在编译链接的时…

C++初识--------带你从不同的角度理解引用的巧妙之处

1.对于展开的理解 我们这里的展开包括命名空间的展开和头文件的展开&#xff0c;两者的含义是不一样的&#xff1a; 头文件的展开就是把头文件拷贝到当前的文件里面&#xff1b; 命名空间的展开不是拷贝&#xff0c;而是因为编译器本身默认是到全局里面去找&#xff0c;当我…