Skip to content

10.2 最短路径

最短路径问题是图论中最经典的问题之一——从导航系统到网络路由,无处不在。在量化金融中,支付系统路由和外汇套利检测都依赖最短路径算法。


Dijkstra 算法

算法简述

Dijkstra 算法求解单源最短路径(边权非负):

  1. 初始化:源点距离 =0=0,其余 \infty;所有节点未访问
  2. 从未访问节点中选取距离最小的节点 uu
  3. uu 的所有邻居 vv:若 dist[u]+w(u,v)<dist[v]dist[u] + w(u,v) < dist[v],更新 dist[v]dist[v]
  4. 标记 uu 为已访问
  5. 重复 2-4 直到所有节点访问完

时间复杂度O((V+E)logV)\mathcal{O}((V+E)\log V)(使用优先队列实现)


手算实例:5 节点图(源点 = 节点 1)

使用与 10.1 节相同的 5 节点加权无向图。

初始状态

节点距节点 1 距离前驱已访问
10
2\infty
3\infty
4\infty
5\infty

第 1 步:选中节点 1

访问节点 1(距离最小=0)。更新邻居 2, 3, 4:

当前距离dist[1]+wdist[1] + w是否更新?新距离新前驱
(1,2)\infty0+2=20 + 2 = 221
(1,3)\infty0+4=40 + 4 = 441
(1,4)\infty0+3=30 + 3 = 331
节点距离前驱已访问
10
221
341
431
5\infty

第 2 步:选中节点 2

未访问节点中最小距离 = 2(节点 2)。访问节点 2,更新邻居:

当前距离dist[2]+wdist[2] + w更新?新距离新前驱
(2,4)32+1=32 + 1 = 3否(相等)3不变
节点距离前驱已访问
10
221
341
431
5\infty

第 3 步:选中节点 4

未访问中最小距离 = 3(节点 4)。访问节点 4,更新邻居:

当前距离dist[4]+wdist[4] + w更新?新距离新前驱
(4,3)43+1=43 + 1 = 4否(相等)4不变
(4,5)\infty3+5=83 + 5 = 884
节点距离前驱已访问
10
221
341
431
584

第 4 步:选中节点 3

未访问中最小距离 = 4(节点 3)。访问节点 3。节点 3 的所有邻居(1, 4)都已访问,无更新。

第 5 步:选中节点 5

最后选中节点 5。已无更多更新。

最终最短路径

起点 → 终点最短距离路径
1 → 221 → 2
1 → 341 → 3 或 1 → 4 → 3
1 → 431 → 4
1 → 581 → 4 → 5

Python 示例

python
import networkx as nx

# 构建加权无向图
G = nx.Graph()
edges = [
    (1, 2, 2),
    (1, 3, 4),
    (1, 4, 3),
    (2, 4, 1),
    (3, 4, 1),
    (4, 5, 5)
]
G.add_weighted_edges_from(edges)

# Dijkstra 最短路径
for target in [2, 3, 4, 5]:
    path = nx.dijkstra_path(G, source=1, target=target, weight='weight')
    dist = nx.dijkstra_path_length(G, source=1, target=target, weight='weight')
    print(f"1 → {target}: 距离 = {dist}, 路径 = {path}")

# --- 输出 ---
# 1 → 2: 距离 = 2, 路径 = [1, 2]
# 1 → 3: 距离 = 4, 路径 = [1, 3]    (也可通过 1→4→3,同距离)
# 1 → 4: 距离 = 3, 路径 = [1, 4]
# 1 → 5: 距离 = 8, 路径 = [1, 4, 5]

支付系统结算(如 CHIPS 或 Fedwire)中,Dijkstra 算法用于寻找银行间资金转移的最优路径——最小化中间行数量或总手续费的支付路径。

区块链闪电网络

区块链中的闪电网络也使用类似的路由算法。在闪电网络中:

  • 顶点:支付通道节点
  • 边:双向支付通道,权重为通道容量或手续费
  • 目标:找到从发送方到接收方、有足够流动性的路径

外汇套利检测

Dijkstra 算法的一个变种也用于检测三角套利机会——将汇率取负对数后,寻找负权环等价于寻找套利机会。

注意:Dijkstra 算法要求边权非负。当图中存在负权边(如某些转换后的成本)时,应使用 Bellman-Ford 算法。Bellman-Ford 通过对图中所有边重复松弛操作(Relaxation——检查"经过当前节点 uuvv 是否比原来记录的路径更短",如果是则更新距离)V1|V|-1 轮(V|V| 为顶点数)来找到最短路径。每轮遍历所有边,尝试用 dist[u]+w(u,v)dist[u] + w(u,v) 更新 dist[v]dist[v]。若第 V|V| 轮还能更新,则说明存在负权环(可无限缩小距离)。算法时间复杂度 O(VE)O(|V||E|),比 Dijkstra 的 O((V+E)logV)O((|V|+|E|)\log|V|) 慢,但能处理负权边。 \n> 下一步:继续学习 10.3 最小生成树

Built with VitePress