Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0c09215

Browse files
committed
added shortest path; added prim's algorithm to heap; improved variables' names
1 parent db763bd commit 0c09215

File tree

4 files changed

+159
-42
lines changed

4 files changed

+159
-42
lines changed

‎basic_algorithm/graph/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ Ongoing...
44

55
[拓扑排序](./topological_sorting.md)
66

7-
[最小生成树](./mst.md)
7+
[最小生成树](./mst.md)
8+
9+
[最短路径](./shortest_path.md)

‎basic_algorithm/graph/mst.md

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
```Python
1010
# Kruskal's algorithm
1111
class Solution:
12-
def getMinRiskValue(self, n, m, x, y, w):
12+
def getMinRiskValue(self, N, M, X, Y, W):
1313

1414
# Kruskal's algorithm with union-find to construct MST
15-
parent = list(range(n + 1))
15+
parent = list(range(N + 1))
1616

1717
def find(x):
1818
if parent[parent[x]] != parent[x]:
@@ -27,68 +27,68 @@ class Solution:
2727
else:
2828
return False
2929

30-
edges = sorted(zip(x, y, w), key=lambdax: x[2])
30+
edges = sorted(zip(W, X, Y))
3131

32-
mst_edges = []
32+
MST_edges = []
3333
for edge in edges:
34-
if union(edge[0], edge[1]):
35-
mst_edges.append(edge)
36-
if find(0) == find(n):
34+
if union(edge[1], edge[2]):
35+
MST_edges.append(edge)
36+
if find(0) == find(N):
3737
break
3838

39-
mst = collections.defaultdict(list)
39+
MST = collections.defaultdict(list)
4040
target = find(0)
41-
for u, v, r in mst_edges:
41+
for w, u, vin MST_edges:
4242
if find(u) == target and find(v) == target:
43-
mst[u].append((v, r))
44-
mst[v].append((u, r))
43+
MST[u].append((v, w))
44+
MST[v].append((u, w))
4545

4646
# dfs to search route from 0 to n
4747
dfs = [(0, None, float('-inf'))]
4848
while dfs:
49-
v, p, max_risk = dfs.pop()
50-
for a, r in mst[v]:
51-
cur_max = max(max_risk, r)
52-
if a == n:
53-
return cur_max
54-
if a != p:
55-
dfs.append((a, v, cur_max))
49+
v, p, max_w = dfs.pop()
50+
for n, w in MST[v]:
51+
cur_max_w = max(max_w, w)
52+
if n == N:
53+
return cur_max_w
54+
if n != p:
55+
dfs.append((n, v, cur_max_w))
5656
```
5757

5858
```Python
5959
# Prim's algorithm
6060
class Solution:
61-
def getMinRiskValue(self, n, m, x, y, w):
61+
def getMinRiskValue(self, N, M, X, Y, W):
6262

6363
# construct graph
6464
adj = collections.defaultdict(list)
65-
for i in range(m):
66-
adj[x[i]].append((y[i], w[i]))
67-
adj[y[i]].append((x[i], w[i]))
65+
for i in range(M):
66+
adj[X[i]].append((Y[i], W[i]))
67+
adj[Y[i]].append((X[i], W[i]))
6868

6969
# Prim's algorithm with min heap
70-
mst = collections.defaultdict(list)
71-
min_heap = [(r, 0, v) for v, r in adj[0]]
70+
MST = collections.defaultdict(list)
71+
min_heap = [(w, 0, v) for v, w in adj[0]]
7272
heapq.heapify(min_heap)
7373

74-
while n not in mst:
75-
r, u, v = heapq.heappop(min_heap)
76-
if v not in mst:
77-
mst[u].append((v, r))
78-
mst[v].append((u, r))
79-
for nei, w in adj[v]:
80-
if nei not in mst:
81-
heapq.heappush(min_heap, (w, v, nei))
74+
while N not in MST:
75+
w, p, v = heapq.heappop(min_heap)
76+
if v not in MST:
77+
MST[p].append((v, w))
78+
MST[v].append((p, w))
79+
for n, w in adj[v]:
80+
if n not in MST:
81+
heapq.heappush(min_heap, (w, v, n))
8282

8383
# dfs to search route from 0 to n
8484
dfs = [(0, None, float('-inf'))]
8585
while dfs:
86-
v, p, max_risk = dfs.pop()
87-
for a, r in mst[v]:
88-
cur_max = max(max_risk, r)
89-
if a == n:
90-
return cur_max
91-
if a != p:
92-
dfs.append((a, v, cur_max))
86+
v, p, max_w = dfs.pop()
87+
for n, w in MST[v]:
88+
cur_max_w = max(max_w, w)
89+
if n == N:
90+
return cur_max_w
91+
if n != p:
92+
dfs.append((n, v, cur_max_w))
9393
```
9494

‎basic_algorithm/graph/shortest_path.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# 最短路径问题
2+
3+
## Dijkstra's Algorithm
4+
5+
思想是 greedy 构造 shortest path tree (SPT),每次将当前距离源点最短的不在 SPT 中的结点加入SPT,与构造最小生成树 (MST) 的 Prim's algorithm 非常相似。可以用 priority queue (heap) 实现。
6+
7+
### [network-delay-time](https://leetcode-cn.com/problems/network-delay-time/)
8+
9+
标准的单源最短路径问题,使用朴素的的 Dijikstra 算法即可,可以当成模板使用。
10+
11+
```Python
12+
class Solution:
13+
def networkDelayTime(self, times: List[List[int]], N: int, K: int) -> int:
14+
15+
# construct graph
16+
graph_neighbor = collections.defaultdict(list)
17+
for s, e, t in times:
18+
graph_neighbor[s].append((e, t))
19+
20+
# Dijkstra
21+
SPT = {}
22+
min_heap = [(0, K)]
23+
24+
while min_heap:
25+
delay, node = heapq.heappop(min_heap)
26+
if node not in SPT:
27+
SPT[node] = delay
28+
for n, d in graph_neighbor[node]:
29+
if n not in SPT:
30+
heapq.heappush(min_heap, (d + delay, n))
31+
32+
return max(SPT.values()) if len(SPT) == N else -1
33+
```
34+
35+
### [cheapest-flights-within-k-stops](https://leetcode-cn.com/problems/cheapest-flights-within-k-stops/)
36+
37+
在标准的单源最短路径问题上限制了路径的边数,因此需要同时维护当前 SPT 内每个结点最短路径的边数,当遇到边数更小的路径 (边权和可以更大) 时结点需要重新入堆,以更新后继在边数上限内没达到的结点。
38+
39+
```Python
40+
class Solution:
41+
def findCheapestPrice(self, n: int, flights: List[List[int]], src: int, dst: int, K: int) -> int:
42+
43+
# construct graph
44+
graph_neighbor = collections.defaultdict(list)
45+
for s, e, p in flights:
46+
graph_neighbor[s].append((e, p))
47+
48+
# modified Dijkstra
49+
prices, steps = {}, {}
50+
min_heap = [(0, 0, src)]
51+
52+
while len(min_heap) > 0:
53+
price, step, node = heapq.heappop(min_heap)
54+
55+
if node == dst: # early return
56+
return price
57+
58+
if node not in prices:
59+
prices[node] = price
60+
61+
steps[node] = step
62+
if step <= K:
63+
step += 1
64+
for n, p in graph_neighbor[node]:
65+
if n not in prices or step < steps[n]:
66+
heapq.heappush(min_heap, (p + price, step, n))
67+
68+
return -1
69+
```

‎data_structure/heap.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,55 @@ class Solution:
171171
return ''.join(result)
172172
```
173173

174-
##Dijkstra's Algorithm
174+
### Prim's Algorithm
175175

176-
本质上也是 greedy + heap 的一种,用于求解图的单源最短路径相关的问题。
176+
实现上是 greedy + heap 的一个应用,用于构造图的最小生成树 (MST)。
177+
178+
### [minimum-risk-path](https://www.lintcode.com/problem/minimum-risk-path/description)
179+
180+
> 地图上有 m 条无向边,每条边 (x, y, w) 表示位置 m 到位置 y 的权值为 w。从位置 0 到 位置 n 可能有多条路径。我们定义一条路径的危险值为这条路径中所有的边的最大权值。请问从位置 0 到 位置 n 所有路径中最小的危险值为多少?
181+
182+
**图森面试真题**。最小危险值为最小生成树中 0 到 n 路径上的最大边权。
183+
184+
```Python
185+
class Solution:
186+
def getMinRiskValue(self, N, M, X, Y, W):
187+
188+
# construct graph
189+
adj = collections.defaultdict(list)
190+
for i in range(M):
191+
adj[X[i]].append((Y[i], W[i]))
192+
adj[Y[i]].append((X[i], W[i]))
193+
194+
# Prim's algorithm with min heap
195+
MST = collections.defaultdict(list)
196+
min_heap = [(w, 0, v) for v, w in adj[0]]
197+
heapq.heapify(min_heap)
198+
199+
while N not in MST:
200+
w, p, v = heapq.heappop(min_heap)
201+
if v not in MST:
202+
MST[p].append((v, w))
203+
MST[v].append((p, w))
204+
for n, w in adj[v]:
205+
if n not in MST:
206+
heapq.heappush(min_heap, (w, v, n))
207+
208+
# dfs to search route from 0 to n
209+
dfs = [(0, None, float('-inf'))]
210+
while dfs:
211+
v, p, max_w = dfs.pop()
212+
for n, w in MST[v]:
213+
cur_max_w = max(max_w, w)
214+
if n == N:
215+
return cur_max_w
216+
if n != p:
217+
dfs.append((n, v, cur_max_w))
218+
```
219+
220+
### Dijkstra's Algorithm
221+
222+
实现上是 greedy + heap 的一个应用,用于求解图的单源最短路径相关的问题。
177223

178224
### [network-delay-time](https://leetcode-cn.com/problems/network-delay-time/)
179225

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /