标号法原理

是一种贪心策略,通过不断拓展已知的最短路径范围,逐步为每个顶点确定最短距离;基本思想可以概括为以下四个要点:

一、Dijkstra 型标号法

1. 两种标号

  • 永久标号:表示从起点到该顶点的最短路径长度已经确定,不再改变。
  • 临时标号:表示从起点到该顶点的当前已知最短路径长度(上界),后续迭代中可能被更新。

2. 核心步骤(迭代更新)

  1. 初始化:起点获得永久标号 00,其余所有顶点获得临时标号 ∞∞。
  2. 选择 :在所有临时标号中,找出值最小的顶点。根据贪心策略,该值即为该顶点的最短路径长度,将其从临时标号改为永久标号
  3. 更新 :检查刚刚获得永久标号的顶点,遍历它的所有邻接点。如果通过该顶点到达邻接点的路径比邻接点当前的临时标号更短,就更新该邻接点的临时标号(即"松弛"操作)。
  4. 终止:重复"选择"和"更新"步骤,直到所有顶点都获得永久标号(或找到了目标点的最短路径)。

3. 核心性质(适用条件)

该思路能够成立的关键在于图中边的权重必须为非负数

  • 因为每次选出的临时标号最小值一旦被转为永久,就不可能通过后续其他顶点(距离更长)绕路来获得更短路径。
  • 如果存在负权边,这种方法会失效,此时需要采用 Bellman-Ford 算法(贝尔曼-福特算法)的思路。

4. 本质思想

这是一种按路径长度递增的顺序产生最短路径的方法。算法并不是一次性求出所有最短路径,而是先找到离起点最近的点,然后利用它去"松弛"周围更远的点,就像水波从起点一圈一圈向外扩散一样,直到覆盖整个网络。

举例说明:

下面通过一个简单的例子来演示标号法(Dijkstra算法)的具体过程。

示例图

我们考虑一个有向图,顶点为 A、B、C、D,A 为起点。边的方向和权重如下:

  • A → B:4
  • A → C:2
  • B → C:1
  • B → D:5
  • C → D:8

(所有权重均为非负数,满足算法使用条件。)

标号法步骤

1. 初始化

  • 起点 A 获得永久标号:0
  • 其余顶点临时标号:B(∞)、C(∞)、D(∞)
  • 已永久顶点集合:{A}

2. 第一次迭代

  • 从临时标号中选出最小值:目前只有 A 有永久标号,我们需从 A 的邻接点开始更新。
  • 实际算法中,每次选当前临时标号最小的顶点转为永久。初始时,只有 A 有永久标号,我们先利用 A 更新邻接点,然后选出临时标号最小的点。
  • 更新 :从 A 出发,可到达 B 和 C。
    • 到 B:min(∞, 0+4) = 4(临时)
    • 到 C:min(∞, 0+2) = 2(临时)
  • 现在临时标号:B(4)、C(2)、D(∞)
  • 选出临时标号最小的顶点:C(2),将其改为永久标号。已永久:A(0)、C(2)

3. 第二次迭代

  • 以 C 为当前永久顶点,更新其邻接点。
  • C 可到达 D:min(∞, 2+8) = 10(临时)
  • 现在临时标号:B(4)、D(10)
  • 选出最小的临时标号:B(4),将其改为永久。已永久:A(0)、C(2)、B(4)

4. 第三次迭代

  • 以 B 为当前永久顶点,更新其邻接点。
  • B 可到达 C 和 D。
    • 到 C:C 已有永久标号 2,且 4+1=5 > 2,不更新。
    • 到 D:min(10, 4+5) = 9(更新临时标号为 9)
  • 现在临时标号:D(9)
  • 选出最小的临时标号:D(9),将其改为永久。已永久:A(0)、C(2)、B(4)、D(9)

5. 结束

所有顶点均获得永久标号,结果如下:

  • A → A:0
  • A → C:2
  • A → B:4
  • A → D:9(路径 A→B→D,总长 4+5=9,比直接 A→C→D 的 2+8=10 更短)

二、 Bellman-Ford 型标号法

1. 算法步骤

这种算法不追求一次确定顶点距离,而是反复执行松弛操作:

  • 初始化所有标号为 ∞,起点为 0
  • 重复 n−1 轮(n 为顶点数),每轮对所有边进行松弛
  • k 轮结束后,标号表示从起点出发经过不超过 k 条边的最短距离
  • 它能处理负权边,并能检测负权环

2. 举例说明

用以下边(起点 A):

  • A→B:3
  • A→C:5
  • B→C:1
  • B→D:2
  • C→B:-1 (负权但不成负环,因为 B→C→B = 1+(-1)=0)
  • C→D:6

依然有负权边,但无负环。

初始化

dist = [A:0, B:∞, C:∞, D:∞]

第1轮

  1. A→B(3): 0+3=3 → B=3

  2. A→C(5): 0+5=5 → C=5

  3. B→C(1): 3+1=4 < 5 → C=4

  4. B→D(2): 3+2=5 → D=5

  5. C→B(-1): 4+(-1)=3 = 3 → 不更新

  6. C→D(6): 4+6=10 > 5 → 不更新

    结果:[0,3,4,5]

第2轮

  1. A→B: 0+3=3 = 3 不更新

  2. A→C: 5 > 4 不更新

  3. B→C: 3+1=4 = 4 不更新

  4. B→D: 3+2=5 = 5 不更新

  5. C→B: 4+(-1)=3 = 3 不更新

  6. C→D: 4+6=10 > 5 不更新

    无变化,提前结束(也可继续至第3轮)。

第2轮无更新,算法终止。最终最短距离:A:0, B:3, C:4, D:5。

问题1:为什么不能存在负权环?

负权环使最短路径失去定义,如果图中存在一个环,且环上所有边的权值之和为负数,那么这个环称为负权环 。由于可以在环上无限次绕行,每绕一圈路径总长度就会减少,因此从起点到环上任意一点(或环上可到达的点)的路径长度可以无限减小,不存在"最短"路径(通常定义为负无穷)。

问题2:为什么最多只需要执行V-1次?

  • 第一轮松弛后,dist[v] 是只使用 1 条边 能到达 vv 的最短距离(即直接边)。
  • 第二轮松弛时,我们可以利用第一轮的结果,通过"在一条边的基础上再接一条边"来构造长度为 2 的路径,并与已有距离比较,从而得到最多 2 条边的最短距离。
  • 依次类推,第 kk 轮结束后,我们实际上已经考虑了所有不超过 kk 条边的路径。

由于最短路径(无负环)不需要超过 ∣V∣−1∣V ∣−1 条边,所以 ∣V∣−1∣V∣−1 轮足以找到所有顶点的最短距离

相关推荐
努力学习的小廉2 小时前
我爱学算法之——动态规划(一)
算法·动态规划
篮l球场2 小时前
前 K 个高频元素
数据结构·算法·leetcode
汉克老师3 小时前
GESP5级C++考试语法知识(十一、递归算法(一))
c++·算法·记忆化搜索·递归算法·递归优化
qq_148115373 小时前
C++网络编程(Boost.Asio)
开发语言·c++·算法
2301_804215413 小时前
内存映射文件高级用法
开发语言·c++·算法
爱喝白开水a3 小时前
春节后普通程序员如何“丝滑”跨行AI:不啃算法,也能拿走AI
java·人工智能·算法·spring·ai·前端框架·大模型
张辰宇-4 小时前
AcWing 5 多重背包问题 II
算法
小则又沐风a4 小时前
类和对象(C++)---上
java·c++·算法
季明洵4 小时前
动态规划及背包问题
java·数据结构·算法·动态规划·背包问题