📅  最后修改于: 2023-12-03 15:28:41.628000             🧑  作者: Mango
给定一个无向图,图中可能存在重边和自环,各边权可能为正、负、零值。图中可能存在负环。请编写一个程序,判断该图是否存在负环。
这道题目可以使用 Bellman-Ford 算法来解决。Bellman-Ford 算法的主要思想在于通过松弛操作来计算到每个点的最短路径。对于给定的图,我们可以对所有的边进行一次松弛操作(即更新起点到该边终点的最短距离),一共进行 $n-1$ 次松弛操作。如果在第 $n$ 次操作中仍然能更新某些边,则说明存在从起点可达的负环。
实现 Bellman-Ford 算法的过程中,我们需要维护一个数组 $dist$,其中 $dist_i$ 表示起点到节点 $i$ 的最短距离。初始时,$dist$ 中所有元素均为正无穷大,除了 $dist_{起点}=0$。
在每次松弛操作时,对于当前遍历到的边 $(u,v,w)$,我们需要检查是否可以通过 $u$ 更新 $v$ 的最短距离。具体地,如果 $dist_u + w < dist_v$,则说明可以通过这条边更新 $dist_v$,我们将其更新为 $dist_u + w$。重复进行 $n-1$ 次松弛操作后,如果还存在可以更新的边,则说明图中存在负环。
def bellman_ford(graph, start):
n = len(graph)
dist = [float('inf')] * n
dist[start] = 0
for _ in range(n-1):
for u in range(n):
for v, w in graph[u]:
if dist[u] + w < dist[v]:
dist[v] = dist[u] + w
for u in range(n):
for v, w in graph[u]:
if dist[u] + w < dist[v]:
return True
return False
由于 Bellman-Ford 算法需要对所有边进行 $n-1$ 次松弛操作,因此其时间复杂度为 $O(nm)$,其中 $n$ 表示图中的节点数,$m$ 表示边数。空间复杂度为 $O(n)$。