SPFA 判负环
SPFA 判负环
大家好,我是Weekoder!
今天我要讲的是接上一次 SPFA 最短路算法衍生而来的一个应用——判断图中是否存在负环。我将介绍两种判负环的方法,都基于 SPFA。
负环的概念
负环是什么?
负环就是在图中的一个环,其边权之和为负数。如下图:
可以看到,这个环的权值和是
如果一个图有负环,则该图没有最短路,因为可以在负环中无限绕圈,不断减少路径长度,一直到
BFS-SPFA 判负环
今天介绍的第一种方法是基于 BFS 的搜索方式的判定方法。在 SPFA 模板的基础上,只修改了一点点,非常容易。它的原理是:维护一个
参考题目:P3385。
bool spfa(int s) {
queue<int> q;
memset(dis, 0x3f, sizeof dis);
memset(vis, 0, sizeof vis);
memset(dp, 0, sizeof dp); // 记得初始化
dis[s] = 0;
vis[s] = 1;
q.push(s);
while (!q.empty()) {
int cur = q.front(); q.pop();
vis[cur] = 0;
for (auto nxt : nbr[cur]) {
int to = nxt.to, w = nxt.w;
if (dis[to] > dis[cur] + w) {
dis[to] = dis[cur] + w;
dp[to] = dp[cur] + 1; // 状态转移方程
if (dp[to] >= n) return 1; // 如果存在负环,则返回1
if (!vis[to]) {
vis[to] = 1;
q.push(to);
}
}
}
}
return 0;
}
DFS-SPFA 判负环
这个方法是我在做 P3199 最小圈的时候,因为不知道为什么
bool spfa(int cur) {
vis[cur] = 1;
for (auto nxt : nbr[cur]) {
int to = nxt.to, w = nxt.w;
if (dis[to] > dis[cur] + w) {
dis[to] = dis[cur] + w;
if (vis[to] || spfa(to)) return 1;
}
}
vis[cur] = 0;
return 0;
}
可以看到,
BFS-SPFA 对比 DFS-SPFA
如果你去实践了一下,你会发现:诶?DFS 的版本过不了模板,BFS 却能过。DFS 是不是比 BFS 慢?不,听我来分析一下他们的区别。DFS-SPFA 其实比 BFS-SPFA 要快得多。你会发现评测记录中其他测试点基本上都是几毫秒,都没有超过
小结
综上所述,SPFA 判负环的方法就是这些了。请不要忘记关注下一次的文章:负环的习题和应用。
再见!
本文作者:Weekoder
本文链接:https://www.cnblogs.com/Weekoder/p/18240226
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步