python - 即使通过了示例测试用例,Dijkstra 算法也不起作用
问题描述
所以我遵循了维基百科的 Dijkstra 算法的伪代码以及 Brilliants。https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm#Pseudocode https://brilliant.org/wiki/dijkstras-short-path-finder/。这是我的代码不起作用。谁能指出我的代码中的缺陷?
# Uses python3
from queue import Queue
n, m = map(int, input().split())
adj = [[] for i in range(n)]
for i in range(m):
u, v, w = map(int, input().split())
adj[u-1].append([v, w])
adj[v-1].append([u, w])
x, y = map(int, input().split())
x, y = x-1, y-1
q = [i for i in range(n, 0, -1)]
#visited = set()
# visited.add(x+1)
dist = [float('inf') for i in range(len(adj))]
dist[x] = 0
# print(adj[visiting])
while len(q) != 0:
visiting = q.pop()-1
for i in adj[visiting]:
u, v = i
dist[u-1] = dist[visiting]+v if dist[visiting] + \
v < dist[u-1] else dist[u-1]
# print(dist)
if dist[y] != float('inf'):
print(dist[y])
else:
print(-1)
解决方案
您的算法未正确实现 Dijkstra 算法。您只是按输入顺序遍历所有节点,并根据节点的当前距离更新到邻居的距离。但是后一个距离不能保证是最短距离,因为您在某些节点“转弯”之前对其进行了迭代。Dijkstra 算法指定处理节点的特定顺序,不一定是输入顺序。
您的算法中缺少的主要成分是优先级队列。您确实 import from Queue
,但从不使用它。此外,它缺少节点标记为已访问,您似乎已经实现了一个概念,但您已将其注释掉。
Wikipedia上的算法大纲解释了在每次迭代的最后一步中使用此优先级队列:
- 否则,选择标记为最小暂定距离的未访问节点,将其设置为新的“当前节点”,并返回步骤 3。
您的代码中目前没有选择距离最小的访问节点的机制。相反,它会根据输入中的顺序选择下一个节点。
要更正您的代码,请查阅同一 Wikipedia 页面上提供的伪代码,我建议您使用优先队列的变体。
在 Python 中,您可以使用heapq
在优先级队列 ( heappush
, heappop
) 上执行操作。
推荐阅读
- javascript - 无法使用 react-native 加载特定网站的图像
- json - 如何使用 kotlinx 在 Kotlin 上使用未知键迭代 JsonElement?
- python - 如何将 SQL 中的一列数据转换为 python 中的列表?
- python - 如何在张量流中逐行旋转张量?
- azure-devops - DevOps:如何在拉取请求中正确使用分支过滤器
- nginx - nginx - OpenShift pod 中未应用日志格式
- javascript - 正则表达式或运算符的奇怪之处
- c# - 在 C# 中以编程方式将 .crt + .key 文件转换为 X509Certificate2
- r - 使用向量中的值在数据框中添加行
- node.js - CORS 错误:“响应中的 'Access-Control-Allow-Origin' 标头的值不能是通配符 '*'...”