📜  门| GATE-CS-2003 |第 40 题(1)

📅  最后修改于: 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)$。