如果你运行Dijkstra算法而不对图进行任何更改,那么有可能你将无法得到源点和目标点之间的最短路径。例如,考虑S和O。现在,找到最短路径确实取决于将O推入队列时正在遍历哪条边。如果你的代码选择了权重为1的边,那么没问题。但是,如果你的代码选择了权重为8的边,那么你的算法就会给出错误的答案。这意味着算法的正确性现在取决于源节点邻接表中输入的边的顺序。
您可以轻松地将图形转换为没有单边循环和平行边的图形。对于单边循环,您需要检查它们的权重是负数还是非负数。如果权重为负,则显然不存在最短路径,因为您可以原地旋转并将路径长度减小到任何限制之下。但是,如果权重为正,则可以丢弃该边缘,因为没有最短路径可以通过该边缘。零权重边缘会产生与任何零权重循环相似的问题:不仅有一个而是无限数量的最短路径,反复通过同一个循环。在这些情况下,明智的做法是从图中删除边缘。对于平行边缘,您可以丢弃除最低权重边缘外的所有边缘。这样做的原因同样简单:如果存在一条通过具有较低权重的平行边缘B的边缘A的最短路径,则可以通过简单地用B替换A来构造更短的路径。因此,没有最短路径可以通过A。
它只需要一个小变化。如果从u到v有多条有向边,并且每条边的权重不同,您可以选择: 选择最小边权进行松弛;或者 对每条边运行松弛。 以上两种方法的复杂度相同,尽管#2中的常数因子值更高。无论哪种情况,您都需要确保在移动到u的下一个相邻节点之前评估u和v之间的所有边。
在您的示例中,从节点S到O,对于Dijkstra算法,这取决于您的图形表示。在创建图形时,对于此算法和其他最短路径算法,您只需要考虑最低加权边,因此在创建图形结构时,仅存储具有最低值的边缘。然后,您可以按预期运行Dijkstra算法。