Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 20582be

Browse files
committed
743-network-delay-time.md Added queue-improved Bellman-Ford algorithm.
1 parent 82fcb95 commit 20582be

File tree

2 files changed

+136
-16
lines changed

2 files changed

+136
-16
lines changed

en/1-1000/743-network-delay-time.md

Lines changed: 79 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ We will send a signal from a given node `k`. Return _the **minimum** time it tak
4141
## Intuition
4242
We can solve it via both **Bellman-Ford algorithm** and **Dijkstra's algorithm**.
4343

44-
`Bellman-Ford algorithm` has less code and can handle the situation of **negative** edge weights, but it is slower than `Dijkstra's algorithm`.
44+
`Bellman-Ford algorithm` has less code and can handle the situation of **negative** edge weights, but it is slower than `Dijkstra's algorithm` if it is not optimized.
45+
The following code will introduce how to optimize.
4546

4647
`Dijkstra's algorithm` always takes the shortest path, so it is more efficient, but it requires writing more code and it cannot handle the situation of **negative** edge weights.
4748

@@ -54,17 +55,21 @@ For a detailed description of **Dijkstra's algorithm**, please refer to [1514. P
5455
* Time: `O(V * E)`.
5556
* Space: `O(V)`.
5657

58+
### Queue-improved Bellman-Ford algorithm (also known as `Shortest Path Faster Algorithm` abbreviated as `SPFA`)
59+
* Time: `O(V * X)` (`X` < `E`).
60+
* Space: `O(V + E)`.
61+
5762
### Dijkstra's algorithm using `heap sort`
5863
* Time: `O(E * log(E))`.
5964
* Space: `O(V + E)`.
6065

6166
## Python
62-
### Standard Bellman-Ford algorithm
67+
### Bellman-Ford algorithm (slow, yet below, I will introduce how to improve its efficiency)
6368
```python
6469
class Solution:
65-
def networkDelayTime(self, edges: List[List[int]], n: int, start: int) -> int:
70+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
6671
min_times = [float('inf')] * (n + 1)
67-
min_times[start] = 0
72+
min_times[start_node] = 0
6873

6974
for _ in range(n - 1):
7075
for source_node, target_node, time in edges: # process edges directly
@@ -84,12 +89,46 @@ class Solution:
8489
return result
8590
```
8691

87-
### Algorithm similar to Bellman-Ford algorithm
92+
A very similar question: [787. Cheapest Flights Within K Stops](./787-cheapest-flights-within-k-stops.md), but if you use the above code, it will not be accepted by LeetCode.
93+
94+
You can try to solve `787. Cheapest Flights Within K Stops` first, then read on.
95+
8896
```python
8997
class Solution:
90-
def networkDelayTime(self, edges: List[List[int]], n: int, start: int) -> int:
98+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
9199
min_times = [float('inf')] * (n + 1)
92-
min_times[start] = 0
100+
min_times[start_node] = 0
101+
102+
for _ in range(n - 1):
103+
# If you remove the next line and always use `min_times`, it can also be accepted.
104+
# But if you print `min_times`, you may see different result. Please try it.
105+
# The values of `min_times` modified in this loop will affect the subsequent `min_times` items in the same loop.
106+
# Please work on `problem 787`: https://leetcode.com/problems/cheapest-flights-within-k-stops/ to better understand this.
107+
min_times_clone = min_times.copy() # addition 1
108+
109+
for source_node, target_node, time in edges: # process edges directly
110+
if min_times_clone[source_node] == float('inf'): # change 1
111+
continue
112+
113+
target_time = time + min_times_clone[source_node] # change 2
114+
115+
if target_time < min_times[target_node]:
116+
min_times[target_node] = target_time
117+
118+
result = max(min_times[1:])
119+
120+
if result == float('inf'):
121+
return -1
122+
123+
return result
124+
```
125+
126+
### A variant of Bellman-Ford algorithm, which can be used to improve the efficiency of Bellman-Ford algorithm below
127+
```python
128+
class Solution:
129+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
130+
min_times = [float('inf')] * (n + 1)
131+
min_times[start_node] = 0
93132
node_to_pairs = defaultdict(set)
94133

95134
for source, target, time in edges: # process nodes first, then their edges
@@ -114,6 +153,39 @@ class Solution:
114153
return result
115154
```
116155

156+
### Queue-improved Bellman-Ford algorithm (also known as `Shortest Path Faster Algorithm` abbreviated as `SPFA`)
157+
```python
158+
class Solution:
159+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
160+
min_times = [float('inf')] * (n + 1)
161+
min_times[start_node] = 0
162+
node_to_pairs = defaultdict(set)
163+
164+
for source, target, time in edges: # process nodes first, then their edges
165+
node_to_pairs[source].add((target, time))
166+
167+
updated_nodes = set([start_node]) # added 1
168+
169+
for _ in range(n - 1):
170+
nodes = updated_nodes.copy() # added 3
171+
updated_nodes.clear() # added 4
172+
173+
for node in nodes: # changed 1
174+
for target_node, time in node_to_pairs[node]: # process edges of the node
175+
target_time = time + min_times[node]
176+
177+
if target_time < min_times[target_node]:
178+
min_times[target_node] = target_time
179+
updated_nodes.add(target_node) # added 2
180+
181+
result = max(min_times[1:])
182+
183+
if result == float('inf'):
184+
return -1
185+
186+
return result
187+
```
188+
117189
### Dijkstra's algorithm using `heap sort` (without `visited`)
118190
```python
119191
import heapq

zh/1-1000/743-network-delay-time.md

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
## 思路
4444
本题可用 **Bellman-Ford算法****Dijkstra算法** 解决。
4545

46-
`Bellman-Ford`算法代码量少,还能处理``权值为**负数**的情况,但较慢
46+
`Bellman-Ford`算法代码量少,还能处理``权值为**负数**的情况,但如果没有被优化过,运行得比较慢。下文代码会介绍如何优化
4747

4848
`Dijkstra算法`因为始终走最短路径,所以执行**效率高**!但代码量大,无法处理``权值为**负数**的情况。
4949

@@ -56,24 +56,38 @@
5656
* 时间: `O(V * E)`.
5757
* 空间: `O(V)`.
5858

59+
### 列队(或集合)优化的 Bellman-Ford 算法 (又称 `最短路径快速算法`,缩写为 `SPFA`)
60+
* Time: `O(V * X)` (`X` < `E`).
61+
* Space: `O(V + E)`.
62+
5963
### Dijkstra 算法(采用`堆排序`
6064
* 时间: `O(E * log(E))`.
6165
* 空间: `O(V + E)`.
6266

6367
## Python
64-
### Standard Bellman-Ford algorithm
68+
### Bellman-Ford 算法(较慢,后文介绍如何性能提升)
69+
一个与本题非常类似的题目: [787. K 站中转内最便宜的航班](./787-cheapest-flights-within-k-stops.md), 然而,如果你用上面同样的代码,会无法通过力扣测试。
70+
71+
你可以先尝试解决`787. K 站中转内最便宜的航班`,然后再继续阅读下文。
72+
6573
```python
6674
class Solution:
67-
def networkDelayTime(self, edges: List[List[int]], n: int, start: int) -> int:
75+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
6876
min_times = [float('inf')] * (n + 1)
69-
min_times[start] = 0
77+
min_times[start_node] = 0
7078

7179
for _ in range(n - 1):
80+
# 删除这一行,始终用`min_times`,也能通过,但`787. K 站中转内最便宜的航班` https://leetcode.cn/problems/cheapest-flights-within-k-stops/ 就通过不了了。
81+
# 如果你打印`min_times`,很可能会发现结果不一样。请尝试下。
82+
# 原因就是本轮循环中修改了的`min_times`的值,有可能在本轮循环中被使用到,对本轮后续的`min_times`产生影响。
83+
# 为更好地理解本行代码,请做 `787. K 站中转内最便宜的航班`。
84+
min_times_clone = min_times.copy() # addition 1
85+
7286
for source_node, target_node, time in edges: # process edges directly
73-
if min_times[source_node] == float('inf'):
87+
if min_times_clone[source_node] == float('inf'): # change 1
7488
continue
7589

76-
target_time = time + min_times[source_node]
90+
target_time = time + min_times_clone[source_node] # change 2
7791

7892
if target_time < min_times[target_node]:
7993
min_times[target_node] = target_time
@@ -86,12 +100,12 @@ class Solution:
86100
return result
87101
```
88102

89-
### Algorithm similar to Bellman-Ford algorithm
103+
### Bellman-Ford 算法的变体,可用于后文的性能提升
90104
```python
91105
class Solution:
92-
def networkDelayTime(self, edges: List[List[int]], n: int, start: int) -> int:
106+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
93107
min_times = [float('inf')] * (n + 1)
94-
min_times[start] = 0
108+
min_times[start_node] = 0
95109
node_to_pairs = defaultdict(set)
96110

97111
for source, target, time in edges: # process nodes first, then their edges
@@ -116,6 +130,40 @@ class Solution:
116130
return result
117131
```
118132

133+
### 列队(或集合)优化的 Bellman-Ford 算法 (Queue-improved Bellman-Ford)
134+
又称 `最短路径快速算法` (`Shortest Path Faster Algorithm` 缩写为 `SPFA`)。
135+
```python
136+
class Solution:
137+
def networkDelayTime(self, edges: List[List[int]], n: int, start_node: int) -> int:
138+
min_times = [float('inf')] * (n + 1)
139+
min_times[start_node] = 0
140+
node_to_pairs = defaultdict(set)
141+
142+
for source, target, time in edges: # process nodes first, then their edges
143+
node_to_pairs[source].add((target, time))
144+
145+
updated_nodes = set([start_node]) # added 1
146+
147+
for _ in range(n - 1):
148+
nodes = updated_nodes.copy() # added 3
149+
updated_nodes.clear() # added 4
150+
151+
for node in nodes: # changed 1
152+
for target_node, time in node_to_pairs[node]: # process edges of the node
153+
target_time = time + min_times[node]
154+
155+
if target_time < min_times[target_node]:
156+
min_times[target_node] = target_time
157+
updated_nodes.add(target_node) # added 2
158+
159+
result = max(min_times[1:])
160+
161+
if result == float('inf'):
162+
return -1
163+
164+
return result
165+
```
166+
119167
### Dijkstra's algorithm using `heap sort` (without `visited`)
120168
```python
121169
import heapq

0 commit comments

Comments
 (0)