【模板】Spfa判负环

本文介绍了如何在Spfa算法基础上添加额外机制来判断图中是否存在负环。通过一个简单的思路,结合Spfa,文章提供了相关博客推荐,并给出了具体代码实现。

【模板】Spfa判负环

给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你判断图中是否存在负权回路。

输入格式
第一行包含整数n和m。

接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

输出格式
如果图中存在负权回路,则输出“Yes”,否则输出“No”。

数据范围
1≤n≤2000,
1≤m≤10000,
图中涉及边长绝对值均不超过10000。

输入样例:
3 3
1 2 -1
2 3 4
3 1 -4
输出样例:
Yes
前言:如果你不了解Spfa算法,请先看这篇文章:

【模板】Spfa

好了,Spfa判负环的原理十分简单,思路就是在Spfa的基础上加一个cnt数组来判断一个点是否形成负环

推荐看的Blog:

具体代码如下:

#include<bits/stdc++.h>
using namespace std;
const int N=2010,M=10010;
int n,m,h[N]
(Negative Cycle Detection)是指在一个判断是否存在一个**总负数**。论中的一个要问题,尤其在最短路径算法中非常关键。例如,Bellman-Ford 算法可以检测中是否存在从源可达的。 --- ## 的常用方法 ### 1. Bellman-Ford 算法(适用于单源最短路径问题) Bellman-Ford 算法不仅可以求单源最短路径,还能检测中是否存在。其核心思想是: - 对所有的进行 `V-1` 次松弛操作(其中 `V` 是顶数),因为在一个不含中,最短路径最多包含 `V-1` 。 - 如果在第 `V` 次松弛操作中仍然可以更新距离,说明存在。 #### Python 实现 Bellman-Ford : ```python def has_negative_cycle(graph, V, src): """ graph: List of edges in the form (u, v, w) V: number of vertices src: source vertex """ dist = [float('inf')] * V dist[src] = 0 # Relax all edges V-1 times for _ in range(V - 1): for u, v, w in graph: if dist[u] != float('inf') and dist[u] + w < dist[v]: dist[v] = dist[u] + w # Check for negative-weight cycles for u, v, w in graph: if dist[u] != float('inf') and dist[u] + w < dist[v]: return True # 存在 return False ``` --- ### 2. SPFA 算法(队列优化的 Bellman-Ford) SPFA 是 Bellman-Ford 的优化版本,使用队列来避免不必要的松弛操作。它也可以用于检测。 #### SPFA 的 Python 实现: ```python from collections import deque def has_negative_cycle_spfa(graph, V, src): """ graph: adjacency list with weights, e.g. graph[u] = [(v, w)] V: number of vertices src: source vertex """ dist = [float('inf')] * V dist[src] = 0 in_queue = [False] * V count = [0] * V queue = deque() queue.append(src) in_queue[src] = True while queue: u = queue.popleft() in_queue[u] = False for v, w in graph[u]: if dist[u] + w < dist[v]: dist[v] = dist[u] + w if not in_queue[v]: queue.append(v) in_queue[v] = True count[v] += 1 if count[v] >= V: return True # 存在 return False ``` --- ### 3. Floyd-Warshall 算法(适用于所有对) Floyd-Warshall 是一种动态规划算法,可以求出所有对的最短路径。如果发现某个到自身的距离为负数,则说明存在。 #### Floyd-Warshall 的 Python 实现: ```python def has_negative_cycle_floyd(graph, V): """ graph: V x V adjacency matrix with weights graph[i][j] = weight of edge i->j, INF if no edge """ dist = [[graph[i][j] for j in range(V)] for i in range(V)] for k in range(V): for i in range(V): for j in range(V): if dist[i][k] + dist[k][j] < dist[i][j]: dist[i][j] = dist[i][k] + dist[k][j] # 如果某个到自己的距离小于0,说明存在 for i in range(V): if dist[i][i] < 0: return True return False ``` --- ## 总结 | 方法 | 时间复杂度 | 是否支持多源 | 是否可检测所有 | |------|------------|--------------|---------------------| | Bellman-Ford | O(VE) | 否(单源) | 是(从源可达的) | | SPFA | 平均 O(E),最坏 O(VE) | 否(单源) | 是(从源可达的) | | Floyd-Warshall | O(V³) | 是(多源) | 是(所有) | --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值