+ O9 q/ ?4 I* Q; y+ d### 原理步骤 " |, E1 P7 I1 }9 P0 q! ^$ K $ Y/ y0 i5 B& s! ]8 `1. **初始化**:3 F( K+ P% c: e# l4 M
- 设置源节点到自己的距离为0,其他节点为无穷大。 , G" m, J3 v5 J6 k; p1 C. o2 {& @1 c3 o5 h# X: L% _
2. **松弛操作**: O0 d2 T+ Q- d - 对所有边进行松弛操作,循环(V-1)次(V为节点数),尝试更新每个边的距离。) u: H, ?$ z) F: Y2 @
* T, }- a: Y& e4 j
3. **检查负权回路**: , j! O" a( k$ P) q T; b - 再次对所有边进行一次松弛检查,如果有边的距离仍能被更新,则说明图中存在负权回路。 3 f# O3 V( w6 @! B4 E; J; B" z/ m5 ?1 G6 N) e, L1 Q
### 示例代码' c6 I* a7 H8 e3 V
8 c& S y% C; w3 E
```python % I: V! n9 l* L% i' S2 L5 y6 wdef bellman_ford(graph, start): & C# r3 X7 K; h# U # 初始化距离 , g5 H6 ?2 K, X6 E7 q* k4 V$ g distances = {node: float('inf') for node in graph}, c' C4 p7 o3 U: h) I
distances[start] = 0 * u) I0 E: V2 `8 W: @, N( F/ A9 j/ `( U5 K9 e0 S
# 松弛操作 . w$ [# U: y( M for _ in range(len(graph) - 1): 6 }+ [ ]/ u8 e8 J: F for u in graph: : b7 Y5 E" [. ?6 [ for v, weight in graph[u].items(): : Q$ ^# `) F ^% f$ C: F if distances[u] + weight < distances[v]:5 U6 ]; G5 C$ f
distances[v] = distances[u] + weight& J4 p$ Z5 N7 I( C/ z
3 Q2 z7 K: Y( [3 T # 检查负权回路. s7 l* A4 W0 l' e. j8 u$ Y
for u in graph:$ R/ Z" S# A! I! p% N, _+ U
for v, weight in graph[u].items():7 L1 x9 l0 b/ i `. `$ Y
if distances[u] + weight < distances[v]:( m5 {5 ?" b- p, m. Q* d0 O; P# L
raise ValueError("Graph contains a negative weight cycle") 4 }" @( ]* I, N" W 3 z5 W6 w7 l( g% W; o/ O0 C E% E2 h+ f return distances- c% M/ f5 b" I( K! s4 _
: G; a, N h9 Y2 [+ l( M$ L1 k# 示例图(带有负权边): V$ m! t4 {; f
graph_with_negative_weight = { A. I& ~& k4 R3 _: }) B6 T 'A': {'B': 1, 'C': 4},7 Z) i5 B( |5 D) c
'B': {'C': -3, 'D': 2}," M: e( t, T1 v: S7 U
'C': {},( |" K) D$ M6 m/ W4 H& {
'D': {'A': -1}, z9 g& x) I) `. H: \
} : ?2 v) R+ f0 |3 A: t0 e5 f0 T* F, M+ }/ p0 k9 K
start_node = 'A' 6 F N, v& [: r9 Y4 R# Rshortest_paths = bellman_ford(graph_with_negative_weight, start_node)3 x! S5 Q) O" Y, t) p
print(shortest_paths) # {'A': 0, 'B': 1, 'C': -2, 'D': 3}8 b' s, P5 z: \
``` " ?7 _/ Y, z1 F/ i6 {) @8 w 1 w O6 v; M1 [- r4 v/ ^## 3. Floyd-Warshall 算法6 P* b* m z G5 _% v! F9 q
4 D8 I2 f/ w; V6 _. WFloyd-Warshall 算法用于寻找图中所有节点之间的最短路径,适用于边权任意的图,包括有负权边但无负权回路的情况。3 P5 ~% N L- W- a& s
( ]/ F8 p% K7 i
### 原理步骤 # J# y' }2 z* r u; M1 Q) e 7 F R4 e2 H5 c# k1. **初始化**:: N2 @7 I3 N. {- {$ \ Z
- 创建一个距离矩阵,初始化为无穷大,源节点到自身的距离置为0,直接相连的节点的距离为边权。! L9 h9 b& U# }4 U L) \
0 v) e8 I- Z0 R/ i- O( i
2. **更新路径**: * D% a9 P% f7 b3 T% y6 c3 x% O - 三重循环遍历所有节点,以每个中间节点尝试更新路径。2 F% Q/ B8 Y' K* \ ^0 Y8 e
# @. ]& Z- u2 Q2 j4 w3. **输出结果**: 2 O% K. W, T7 p5 V - 最终得到的矩阵即为每对节点之间的最短路径长度。3 M" H: Z8 V1 D' s0 S
' h/ Q& g a9 g# _' d2 B
### 示例代码 1 ]9 {6 _) v6 U" T* B3 E: O 1 q- P: N# ~2 o; w```python # H2 g4 m% @. }+ Cdef floyd_warshall(graph): 7 R/ g: h2 F3 }% l" k& V! v ? # 初始化距离矩阵 ( Y8 K0 c7 c4 |. A( F nodes = list(graph.keys()) 4 e. h" n& F& J" J4 Q4 v. ]8 \3 i distances = {node: {n: float('inf') for n in nodes} for node in nodes} , P6 T2 G' h' e- ?) s+ {& I( p. J9 H9 } j! R+ w' g
for u in nodes:- I2 ^- J& ?" |; U' p5 D( ~6 Z
distances[u][u] = 0( v8 N- R- `. d8 A7 I5 e* K/ g" x
for v, weight in graph[u].items():& i& G1 v+ O( C, v
distances[u][v] = weight$ S: x, M+ o ]( ^: j
* C. p) d' g. w: W( Z( k) U
# 更新路径% G6 b4 N6 _: B1 s
for k in nodes:) u3 W2 [. u( F" \
for i in nodes: , \1 w; ]$ Q. O6 ?! s9 e for j in nodes:+ a5 ]+ A0 @: J" e* D# Q0 I
if distances[i][j] > distances[i][k] + distances[k][j]: - j# c0 ~4 b9 l/ i# \ distances[i][j] = distances[i][k] + distances[k][j]% D1 [; d0 n& B1 t* c. u
5 r5 |7 s8 Y, k* i3 E! D2 Q7 ~ return distances4 ?+ C* g/ D8 I! F2 E# R( Q
5 w5 d% n! d6 e6 b. ~* |
# 示例图(可以含负权边) 1 u2 c; z$ ^$ `( z" ]8 |5 R* K/ Egraph_for_floyd = { 5 j, C& R2 c! y& }1 |* C7 Z 'A': {'B': 3, 'C': 8, 'D': -4}, . z" M; W o! {) n5 ]1 I, i 'B': {'C': 1, 'D': 7}, ' e" p) B `" ]* E' [ 'C': {'B': 4}, ' c! d, |$ }9 W2 t& L8 p 'D': {'A': 2, 'C': -5}- r5 R3 R, `2 ], a
} 5 H( f/ h& `5 l! `0 |9 O+ X7 N( P. g) \; K3 Z9 j! S
shortest_paths_matrix = floyd_warshall(graph_for_floyd)( v$ a. U- _ R: j
for row in shortest_paths_matrix.items():7 X* @3 l" k; n5 v
print(row) 8 B) L `6 p7 i/ b6 w``` 6 R& \; S7 f2 H: k& j / d5 _& p5 b2 t6 ~: b8 e## 总结 0 G }* s" ]4 o( f; Y: S! r+ B 4 y, Y" w9 Q9 F- **Dijkstra 算法**适合用于无负权边图,时间复杂度为 \(O((V + E) \log V)\),其中 \(V\) 为节点数,\(E\) 为边数。" k/ F6 V7 ]0 Q" |& H
- **Bellman-Ford 算法**适合处理含负权边的图,时间复杂度为 \(O(VE)\)。 8 u6 c! T) F4 `" q& J, B' f- **Floyd-Warshall 算法**用于所有节点对最短路径计算,时间复杂度为 \(O(V^3)\)。4 \2 b: r& {6 g8 m% L* l
, g( F- B1 v: M5 t, B6 Y/ k
不同算法适用于不同的问题场景,选择适合的算法是解决最短路径问题的关键。如果需要更详细的介绍或有特定问题,欢迎进一步询问!6 h# l" `& _& c+ _" f
! F: w! J/ p, ?; f" n" ?
$ `+ q. \$ ]0 N# J# c. K
$ I4 }0 [1 n5 M. Q! B# x2 ^