CC

自然万物都趋向从有序变得无序

0%

leetcode-2045 到达目的地的第二短时间

2045. 到达目的地的第二短时间 - 力扣(LeetCode) (leetcode-cn.com)

题目

城市用一个 双向连通 图表示,图中有 n 个节点,从 1 到 n 编号(包含 1 和 n)。图中的边用一个二维整数数组 edges 表示,其中每个 edges[i] = [ui, vi] 表示一条节点 ui 和节点 vi 之间的双向连通边。每组节点对由 最多一条 边连通,顶点不存在连接到自身的边。穿过任意一条边的时间是 time 分钟。

每个节点都有一个交通信号灯,每 change 分钟改变一次,从绿色变成红色,再由红色变成绿色,循环往复。所有信号灯都 同时 改变。你可以在 任何时候 进入某个节点,但是 只能 在节点 信号灯是绿色时 才能离开。如果信号灯是  绿色 ,你 不能 在节点等待,必须离开。

第二小的值 是 严格大于 最小值的所有值中最小的值。

例如,[2, 3, 4] 中第二小的值是 3 ,而 [2, 2, 4] 中第二小的值是 4 。
给你 n、edges、time 和 change ,返回从节点 1 到节点 n 需要的 第二短时间 。

注意:

你可以 任意次 穿过任意顶点,包括 1 和 n 。
  你可以假设在 启程时 ,所有信号灯刚刚变成 绿色 。

题意

给定一个无向无环图,求节点1到节点n的次短路径。

思路

最短路的变种,次短路径。

注意题目每一条路的时间固定,并且节点有红绿灯,只有绿灯能通行,需要判断当前节点是否为绿灯,不是绿灯则需要等待。

dijkstra求最短路,每次是维护一个数组dis[i],表示起点到当前节点i的最短距离(此题距离等于题目描述的时间)。那么类似于求次小值的思想,可以再维护一个数组dis1[i],表示表示起点到当前节点i的次短距离,次短距离需要严格小于最短距离。相比于求最短路径只是多维护了一个数组。

并且如果当前节点是红灯,那么需要等待至绿灯。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
* @File Name :leecode-2045.cpp
* @Author :cc
* @Version :1.0.0
* @Date :2022/1/24 10:32
* @Description :
* @Function List :
* @History :
*/

#include "iostream"
#include "vector"
#include "cstring"
#include "queue"
#include "algorithm"

using namespace std;

struct edge {
int v, d;
edge(int cv, int cd) : v(cv), d(cd) {}
};

class Solution {
public:
static const int maxn = 1e4 + 10;
int d[maxn], d2[maxn];
vector<edge> e[maxn];

int secondMinimum(int n, vector<vector<int>> &edges, int time, int change) {

for (auto &x: edges) {
e[x[0]].emplace_back(time, x[1]);
e[x[1]].emplace_back(time, x[0]);
}
dijkstra(1, n, change);
return d2[n];
}

void dijkstra(int s, int n, int change) {
memset(d, 0x7f, sizeof d);
memset(d2, 0x7f, sizeof d2);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> que;

d[s] = 0;
que.emplace(0, s);
while (!que.empty()) {
pair<int, int> p = que.top();
que.pop();
if (p.first > d2[p.second]) continue;
if ((p.first / change) & 1) p.first =p.first+ change-p.first%change;

for (int i = 0; i < e[p.second].size(); i++) {
int v = p.first + e[p.second][i].v;
int dd = e[p.second][i].d;

if (v < d[dd]) {
swap(d[dd], v);
que.emplace(d[dd], dd);
}
if (v > d[dd] && v < d2[dd]) {
d2[dd] = v;
que.emplace(v, dd);
}
}
}
}
};