You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Bellman-Ford算法负环检测实现出错及TLE问题求助

Bellman-Ford负环检测的错误修复与优化

问题背景

用Python实现Bellman-Ford算法检测图中的负环,用于解决CSES的负环检测问题,但遇到错误答案(WA)和超时(TLE)问题。原代码如下:

def bellman_ford(n, edges):
    dist = [float('inf')] * (n + 1)
    dist[1] = 0
    prev = [-1] * (n + 1)
    for _ in range(n - 1):
        for u, v, w in edges:
            if dist[u] != float('inf') and  dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                prev[v] = u
    for u, v, w in edges:
        if dist[u]!=float('inf') and dist[u] + w < dist[v]:
            cycle = [v]
            prev[v] = u
            while u != v:
                cycle.append(u)
                u = prev[u]
            cycle.append(v)
            return True, cycle[::-1]
    return False, None
n, e = map(int, input().split())
edges = []
for _ in range(e):
    u, v, w = map(int, input().split())
    edges.append((u, v, w))

chk, cycle = bellman_ford(n, edges)
if chk == True:
    print("YES")
    print(*cycle)
else:
    print("NO")

问题分析与修复方案

1. 错误答案(WA):仅检测从节点1可达的负环

原代码仅将dist[1]初始化为0,其余节点设为无穷大,这只能检测从节点1可达的负环。但题目要求检测图中任意存在的负环,如果负环不在节点1的可达区域内,代码会漏判,导致WA。

修复:将所有节点的初始距离设为0,相当于添加一个虚拟源点向所有节点连权重为0的边,确保无论负环在图的哪个区域都能被检测到。

2. 错误答案(WA):环的查找逻辑错误

原代码在找到可松弛的边u->v后,直接修改prev[v] = u再回溯找环,这种逻辑可能因prev指针指向问题无法正确追踪环,甚至陷入死循环。

修复:当找到可松弛的边时,从v出发沿prev指针走n步(图最多n个节点,走n步必然进入环),找到环中的一个节点,再从该节点回溯直到回到自身,构建完整环。

3. 超时(TLE):输入处理效率低

Python的input()函数在处理大量输入时速度慢,循环调用会导致超时。

修复:使用sys.stdin.read()一次性读取所有输入,再分割处理,大幅提升输入速度。

修复后的代码

import sys

def bellman_ford(n, edges):
    dist = [0] * (n + 1)  # 初始化所有节点距离为0,覆盖所有负环场景
    prev = [-1] * (n + 1)
    
    # 松弛阶段:加入提前终止优化
    for i in range(n):
        updated = False
        for u, v, w in edges:
            if dist[u] != float('inf') and dist[u] + w < dist[v]:
                dist[v] = dist[u] + w
                prev[v] = u
                updated = True
        if not updated:
            break  # 无更新时提前退出,减少计算量
    
    # 检测负环并构建环路径
    for u, v, w in edges:
        if dist[u] != float('inf') and dist[u] + w < dist[v]:
            # 找到环中的一个节点
            current = v
            for _ in range(n):
                current = prev[current]
            
            # 回溯生成完整环
            cycle = []
            start = current
            while True:
                cycle.append(current)
                current = prev[current]
                if current == start:
                    cycle.append(current)
                    break
            return True, cycle
    
    return False, None

def main():
    data = sys.stdin.read().split()
    ptr = 0
    n = int(data[ptr])
    ptr +=1
    e = int(data[ptr])
    ptr +=1
    edges = []
    for _ in range(e):
        u = int(data[ptr])
        ptr +=1
        v = int(data[ptr])
        ptr +=1
        w = int(data[ptr])
        ptr +=1
        edges.append((u, v, w))
    
    chk, cycle = bellman_ford(n, edges)
    if chk:
        print("YES")
        print(*cycle)
    else:
        print("NO")

if __name__ == "__main__":
    main()

额外优化说明

  • 松弛阶段加入updated标记,当某一轮无距离更新时提前退出,减少不必要的计算。
  • 环的查找逻辑更健壮,确保能正确提取完整的负环路径。

内容的提问来源于stack exchange,提问作者Anand Singh1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 00:27:22