为什么 Dijkstra 算法在负权重情况下会失效?


简介

Dijkstra 算法是一种广泛使用的图遍历算法,用于查找图中两个顶点之间的最短路径。它高效且在处理非负权重图时能保证最佳结果。但是,当引入负权重时,Dijkstra 算法将无法产生正确的结果。在本文中,我们将探讨其失效的原因,并讨论使用 C 语言处理图中负权重的三种不同方法。我们将对每种方法进行逐步说明,并附带相应的代码和输出。

理解 Dijkstra 算法

Dijkstra 算法通过迭代地扩展从源顶点到图中所有其他顶点的最短路径来工作,直到到达目标顶点。它维护一个待处理顶点的集合,称为“未访问集合”,并跟踪从源到每个顶点的已知最短距离。

最初,到源顶点的距离设置为零,所有其他距离设置为无穷大。随着算法的进行,它选择未访问集合中距离最小的顶点,检查其相邻顶点,如果找到更短的路径,则更新其距离。此过程持续进行,直到到达目标顶点或没有更多顶点可访问。

负权重的问题

Dijkstra 算法中负权重最主要的问题在于,它假设到达任何给定顶点的最短路径总是通过按从源到顶点的距离递增顺序访问顶点来找到的。然而,当引入负权重时,这个假设就会失效,导致结果不准确。

为了理解为什么会发生这种情况,让我们考虑一个 Dijkstra 算法失效的例子。假设我们有一个包含三个顶点的图:

A、B 和 C 连接如下:A →(-1)→ B →(-2)→ C

假设源顶点是 A,Dijkstra 算法最初会将到 B 的距离设置为 -1,将到 C 的距离设置为无穷大。但是,当我们考虑权重为 -2 的从 B 到 C 的边时,该算法将错误地将到 C 的距离更新为 -3,认为路径 A → B → C 比当前路径 A → C 更短。

该算法未能识别 -2 的负权重进一步减少了从 B 到 C 的距离,使得路径 A → C 比 A → B → C 更短。这种不正确的更新导致最短路径计算错误。

C语言代码实现

现在让我们看一下 Dijkstra 算法在 C 语言中的代码实现,重点是它在遇到负权重时的局限性。

示例

#include <stdio.h>
#include <stdbool.h>
#include <limits.h>

#define G 4

int short_dst(int dt[], bool visited[]) {
   int min = INT_MAX, x;

   for (int t = 0; t < G; t++)
      if (visited[t] == false && dt[t] < min)
         min = dt[t], x = t;

      return x;
}

void dkst(int graph[G][ G], int src) {
   int dist[G];
   bool visited[G];

   for (int i = 0; i < G; i++) {
      dist[i] = INT_MAX;
      visited[i] = false;
   }

   dist[src] = 0;

   for (int count = 0; count < G - 1; count++) {
      int u = short_dst(dist, visited);
      visited[u] = true;

      for (int t = 0; t < G; t++) {
         if (!visited[t] && graph[u][t] && dist[u] != INT_MAX && dist[u] + graph[u][t] < dist[t])
            dist[t] = dist[u] + graph[u][t];
      }
   }

   printf("V\t Distance from Source\n");
   for (int i = 0; i < G; i++)
      printf("%d\t%d\n", i, dist[i]);
}

int main() {
   int graph[G][ G] = {{0, 1, INT_MAX, INT_MAX},
                        {INT_MAX, 0, INT_MAX, INT_MAX},
                        {INT_MAX, INT_MAX, 0, -2},
                        {INT_MAX, INT_MAX, INT_MAX, 0}};

   dkst(graph, 0);

   return 0;
}

输出

V	Distance from Source
0	0
1	1
2	-2147483648
3	-2147483648

结论

Dijkstra 算法是查找具有非负权重的图中最短路径的高效且可靠的算法。但是,当图包含负权重时,它将无法产生精确的结果。该算法在处理负权重时所做的不正确假设会导致错误的最短路径计算。虽然 Dijkstra 算法在处理负权重方面存在局限性,但在显示非负权重的场景中,它仍然是一个重要的工具。通过理解其失效的原因并研究替代算法(如 Bellman-Ford 算法),我们可以在选择最合适的算法来解决图相关问题时做出明智的选择,从而确保在各个领域都能获得效率和准确的结果。

更新于:2023年8月25日

浏览量:317

开启你的职业生涯

完成课程获得认证

开始学习
广告