一、摘要

本文介绍了一种使用BFS求无向图中第二短的距离的算法,本文算法参考自Python3 BFS找出第二短路径。通过使用BFS求出题目中给出的路径图(无向联通图)从节点1到节点n的第二短的路径,再根据路径长度计算出需要耗费的时间。其实在LeetCode官网本题目的题解栏目下已经有很多优秀的题解了,本文除了是使用C++与其他题解有些许不同外无任何优势。还是建议读者阅读其他高赞题解。

二、题解

由于给给节点上红灯、绿灯的亮暗是一致的,因此将各节点间的边长视作1,只要求出从节点0节点n-1经过的路径长度即可得到总的耗费时间。

因此本题就变成了求节点0节点n-1第二短的长度

需要注意的是,我们要求的是绝对的第二短的路径,如果有两条最短的不同路径长度都为x,那么我还需要继续求得一个大于x的第二短路径。既然是等边长图中,求最短路径我们可以使用BFS。

使用一个队列queue<pair<int, int>>记录所搜到的节点id和从节点0到该节点id的耗时

为了求第二短的距离因此我们是用两个数组vector<int> firstvector<int> second分别记录节点0节点id的第一、二短耗时(初始时都设为最大值,在C++中即为INT_MAX)。

在使用队列进行bfs算法时:

  • 如果下一个可能要入队列的节点n_id需要的耗时n_time小于first[n_id],那么说明节点0节点n_id的最短耗时为n_time,需要入队pair<int,int>(n_id, n_time)``。
  • 如果下一个可能要入队列的节点n_id需要的耗时n_time等于first[n_id],那么说明存在重复的 从节点0节点n_id的耗时相同、但路径不同 的最短耗时,此时不需要入队;
  • 如果下一个可能要入队列的节点n_id需要的耗时n_time大于first[n_id],且小于second[n_id],那么说明节点0节点n_id的第二短耗时为n_time,需要入队pair<int, int>(n_id, n_time)
  • 如果下一个可能要入队列的节点n_id需要的耗时n_time大于等于second[n_id],那么说明存在重复的 从节点0节点n_id的耗时相同、但路径不同 的第二短耗时、或者这是第三短的耗时,此时不需要入队;

代码如下:

class Solution {
public:
// 图的节点
struct Node{
int idx; // 节点id
vector<int> neighbor; // 相邻的节点id
Node(int i):idx(i){}
}; // 根据此时的时间now计算经过一条边,到达下一个节点的时间
int getNextTime(int now, int time, int change){
if((now/change)%2==0){
now += time;
}else{
now += (change - now%change)+time;
}
return now;
}
int secondMinimum(int n, vector<vector<int>>& edges, int time, int change) {
nodes_.resize(n);
for(int i=0; i<n; i++){
nodes_[i] = new Node(i);
}
// 建图
for(int i=0; i<edges.size(); i++){
int a = edges[i][0] - 1;
int b = edges[i][1] - 1;
nodes_[a]->neighbor.push_back(b);
nodes_[b]->neighbor.push_back(a);
} queue<pair<int, int>> que;
vector<int> first(n, INT_MAX); // first记录到达节点i最短的耗时
vector<int> second(n, INT_MAX); // second记录到达节点i第二短的耗时 que.push(pair<int, int>(0,0)); // 将(0,0)入队,表示达到节点0的耗时为0 while(que.empty()==false){
int id = que.front().first;
int now = que.front().second;
que.pop();
for(int i=0; i<nodes_[id]->neighbor.size(); i++){
int n_id = nodes_[id]->neighbor[i];
int n_time = getNextTime(now, time, change);
if(n_id==n-1){ // 如果是第n个节点
if(first[n_id]==INT_MAX){ // 第一次到达节点n-1,更新first,且pair<int,int>(n_id,n_time)入队
first[n_id] = n_time;
que.push(pair<int, int>(n_id, n_time));
}else if(n_time>first[n_id] && second[n_id]==INT_MAX){ // 到达节点n-1的第二短距离,返回答案
second[n_id] = n_time;
return n_time;
}
}else{
if(first[n_id]==INT_MAX){ // 第一次到达节点n_id,更新first,且pair<int,int>(n_id,n_time)入队
first[n_id] = n_time;
que.push(pair<int, int>(n_id, n_time));
}else if(n_time>first[n_id] && second[n_id]==INT_MAX){ // 到达节点n-1的第二短的距离,更新second,且pair<int,int>(n_id,n_time)入队
second[n_id] = n_time;
que.push(pair<int, int>(n_id, n_time));
}
}
}
}
return 0;
}
vector<Node*> nodes_;
};

复杂度分析:

  • 时间复杂度:O(n+m)
  • 空间复杂度:O(n+m)

    其中n为节点个数,m为边个数

[LeetCode] 2045. 到达目的地的第二短时间的更多相关文章

  1. 构造定律(constructal law)-构造定律作为第二个时间箭头,将和热力学第二定律一道将宇宙推向无序。

    优化系统结构,使信息和物质流在结构内的流动更畅通. 构造定律(constructal law) 由Adrian Bejan于1995创立的构造定律(constructal law):   For a ...

  2. Leetcode春季打卡活动 第二题:206. 反转链表

    Leetcode春季打卡活动 第二题:206. 反转链表 206. 反转链表 Talk is cheap . Show me the code . /** * Definition for singl ...

  3. 广搜最短路(最短时间到达目的地),POJ(3669)

    题目链接:http://poj.org/problem?id=3669 解题报告: 1.流星坠落的点,四周和自己本身都被毁灭,不断更新每个点被毁灭的时候的最短时间. 2.搜索终点是,到达某个点,这个不 ...

  4. [LeetCode] Next Closest Time 下一个最近时间点

    Given a time represented in the format "HH:MM", form the next closest time by reusing the ...

  5. 动态规划之DP中判断是否到达某一状态(最短时间是什么)?

    codevs1684 垃圾陷阱  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold   题目描述 Description 卡门——农夫约翰极其珍视的一条Holste ...

  6. [LeetCode] Employee Free Time 职员的空闲时间

    We are given a list schedule of employees, which represents the working time for each employee. Each ...

  7. LeetCode 176. Second Highest Salary (第二高的薪水)

    题目标签: 题目给了我们一个工资表,让我们返回第二高的工资. 利用Max,把第一高的工资找到,然后利用 NOT IN,去找到第二高的工资. Java Solution: Runtime:  153ms ...

  8. leetcode.1266访问所有点的最小时间

    平面上有 n 个点,点的位置用整数坐标表示 points[i] = [xi, yi].请你计算访问所有这些点需要的最小时间(以秒为单位). 你可以按照下面的规则在平面上移动: 每一秒沿水平或者竖直方向 ...

  9. Java实现 LeetCode 754 到达终点数字(暴力+反向)

    754. 到达终点数字 在一根无限长的数轴上,你站在0的位置.终点在target的位置. 每次你可以选择向左或向右移动.第 n 次移动(从 1 开始),可以走 n 步. 返回到达终点需要的最小移动次数 ...

  10. 第二章 时间控件(DateTime Picker)

    这家伙太懒了,碰到问题才写博文,嘿嘿. 好了进入正题,二话不说,先放地址: 中文:http://www.bootcss.com/p/bootstrap-datetimepicker/index.htm ...

随机推荐

  1. Java 将PDF转为PowerPoint (2行代码)

    通过编程实现PDF转PPT的功能,可以自动化转换过程,减少手动操作的工作量,并根据需要进行批量转换.将PDF文件转换为PPT文档后,可以利用PPT的丰富功能和动画效果,达到更好的演示效果. 在Java ...

  2. Mysql 创建外键、索引的问题

    总结: 创建外键的列,要求必须创建索引,通常我们只需要创建外键就可,索引他会自动创建.若是索引那里已经存在了组合索引,那么组合索引前面的第一列已经有了索引,所以创建外键的时候不会自动创建,但是后面的列 ...

  3. SVC服务的发布

    目录 服务的发布 发布的方式 1.NodePort 方法一:创建的时候直接指定类型 方法二:在线修改(将其他类型改为NodePort) 2.LoadBalance 3.Ingress(推荐/重点) 服 ...

  4. 从零开始学正则(七:终章),详解常用正则API与你可能不知道的正则坑

     壹 ❀ 引 花了差不多半个月的晚上时间,正则入门学习也步入尾声了,当然正则的学习还将继续.不得不说学习成效非常明显,已能看懂大部分正则以及写出不太复杂的正则,比如帮组长写正则验证文件路径正确性,再如 ...

  5. NC20154 [JSOI2007]建筑抢修

    题目链接 题目 题目描述 小刚在玩JSOI提供的一个称之为"建筑抢修"的电脑游戏:经过了一场激烈的战斗,T部落消灭了所有z部落的入侵者.但是T部落的基地里已经有N个建筑设施受到了严 ...

  6. 多线程系列(三) -synchronized 关键字使用详解

    一.简介 在之前的线程系列文章中,我们介绍了线程创建的几种方式以及常用的方法介绍. 今天我们接着聊聊多线程线程安全的问题,以及解决办法. 实际上,在多线程环境中,难免会出现多个线程对一个对象的实例变量 ...

  7. Java并发编程实例--13.方法同步(synchronized)

    使用synchronized关键字去控制对某个方法的并发调用. 某一时段内,只能有一个线程可以读取该方法. 其他线程需要等待前面线程调用完毕后方可调用. 不过,静态方法有着不同的行为. 虽然也是每次只 ...

  8. [攻防世界][Web]PHP2

    打开靶机对应的url 就一行字 Can you anthenticate to this website? 第一感觉就需要做目录文件扫描 使用御剑和dirsearch进行扫描,发现一个文件 index ...

  9. Vulnhub内网渗透DC-7靶场通关

    个人博客: xzajyjs.cn DC系列共9个靶场,本次来试玩一下一个 DC-7,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题.靶场推 ...

  10. 【Azure 应用服务】在创建App Service时,遇见“No available instances to satisfy this request. App Service is attempting to increase capacity.”错误

    问题描述 在创建新的App Service,遇见了资源不满足当前需求的提示.详细消息为: "Code": "Conflict","Message&qu ...