当然,对于Spfa判负环,实际上还有优化:就是把判断单个点的入队次数大于n改为:如果总的点入队次数大于所有点两倍

时有负环,或者单个点的入队次数大于sqrt(点数)有负环。这样时间复杂度就降了很多了。

判断给定的有向图中是否存在负环。

利用 spfa 算法判断负环有两种方法:

1) spfa 的 dfs 形式,判断条件是存在一点在一条路径上出现多次。

2) spfa 的 bfs 形式,判断条件是存在一点入队次数大于总顶点数。

代码如下:

法 1 (spfa 的 dfs 形式):

#include <iostream>

#include <cstdio>

#include <cstring>

using namespace std;

const int oo = 1 << 30;

const int maxn = 1010;

struct Edge {

int u, v, t, next;

}edge[2010];

int prev[maxn], p[maxn], d[maxn];

bool vis[maxn], flag;

int tot;

void addEdge(int u, int v, int t) {

edge[tot].u = u;

edge[tot].v = v;

edge[tot].t = t;

edge[tot].next = prev[u];

prev[u] = tot ++;

}

void spfa(int u) {

int v;

for (int i = prev[u]; i != -1; i = edge[i].next) {

v = edge[i].v;

if (d[u] + edge[i].t < d[v]) {

if (vis[v]) {            //存在一点在一条路径上出现多次

flag = true;

return ;

}

else {

d[v] = d[u] + edge[i].t;

vis[v] = true;

spfa(v);

}

}

}

}

int main() {

//freopen("input.txt", "r", stdin);

//freopen("output.txt", "w", stdout);

int T;

int a, b, t;

int n, m;

scanf("%d", &T);

while (T --) {

scanf("%d%d", &n, &m);

memset(prev, -1, sizeof(prev));

tot = 0;

for (int i = 1; i <= m; i ++) {

scanf("%d%d%d", &a, &b, &t);

addEdge(a, b, t);

}

memset(vis, false, sizeof(vis));

fill(d, d + n, oo);

d[0] = 0;

flag = false;

spfa(0);

if (flag) printf("possible\n");

else printf("not possible\n");

}

return 0;

}

法 2 (spfa 的 bfs 形式):

#include <iostream>

#include <cstdio>

#include <cstring>

#include <queue>

using namespace std;

const int oo = 1 << 30;

const int maxn = 1010;

struct Edge {

int u, v, t, next;

}edge[2010];

int prev[maxn], p[maxn], d[maxn], in[maxn];

bool vis[maxn];

int tot;

queue<int> q;

void addEdge(int u, int v, int t) {

edge[tot].u = u;

edge[tot].v = v;

edge[tot].t = t;

edge[tot].next = prev[u];

prev[u] = tot ++;

}

bool spfa(int n) {

int u, v;

while (!q.empty()) q.pop();

memset(vis, false, sizeof(vis));

memset(in, 0, sizeof(in));

fill(d, d + n, oo);

d[0] = 0; vis[0] = true;

q.push(0);

while (!q.empty()) {

u = q.front();

vis[u] = false;

for (int i = prev[u]; i != -1; i = edge[i].next) {

v = edge[i].v;

if (d[u] + edge[i].t < d[v]) {

d[v] = d[u] + edge[i].t;

if (!vis[v]) {

in[v] ++;

if (in[v] > n) return true;                //存在一点入队次数大于总顶点数

vis[v] = true;

q.push(v);

}

}

}

vis[u] = false;

q.pop();

}

return false;

}

int main() {

//freopen("input.txt", "r", stdin);

//freopen("output.txt", "w", stdout);

int T;

int a, b, t;

int n, m;

scanf("%d", &T);

while (T --) {

scanf("%d%d", &n, &m);

memset(prev, -1, sizeof(prev));

tot = 0;

for (int i = 1; i <= m; i ++) {

scanf("%d%d%d", &a, &b, &t);

addEdge(a, b, t);

}

if (spfa(n)) printf("possible\n");

else printf("not possible\n");

}

return 0;

}

spfa 判断负环 (转载)相关推荐

  1. POJ 3259 Wormholes【最短路/SPFA判断负环模板】

    农夫约翰在探索他的许多农场,发现了一些惊人的虫洞.虫洞是很奇特的,因为它是一个单向通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径 ...

  2. UVA 558 SPFA 判断负环

    这个承认自己没看懂题目,一开始以为题意是形成环路之后走一圈不会产生负值就输出,原来就是判断负环,用SPFA很好用,运用队列,在判断负环的时候,用一个数组专门保存某个点的访问次数,超过了N次即可断定有负 ...

  3. 负环——spfa判断负环的两种方式

    第一种:(不推荐) 统计每个点的入队次数,如果某一个点入队了n次,则说明存在负环. 第二种: 统计当前每个点的最短路的边数,如果存在负环,负环上的某一个点的最短路边数一定会是正无穷,只要边数超过n(节 ...

  4. 算法基础课-搜索与图论-spfa-AcWing 852. spfa判断负环:spfa求负环板子

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: dist[x] 表示从源点到x点的最短距离. spfa算法求最短路的算法步骤: 初始化一个队列,将起点入队. 取出队头元素t,遍历它 ...

  5. PKU3259-Wormholes(SPFA判断负环,含题意)

    题目: 一开始被题目的梦幻给弄的晕乎乎.的却,作者很会yy. 意思是: 一个农夫有cas个田地,然后每个田地里面有nodeNum个结点,结点之间可能有多条路径(这是一个无向图),田地里还有w个虫洞(虫 ...

  6. spfa判断负环( 负环判定 + spfa )

    给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 impossible. 数据保证 ...

  7. AcWing 852. spfa判断负环(spfa or bellman)

    题目链接 https://www.acwing.com/problem/content/description/854/ 思路 思路一 我们定义一个数组cnt,cnt[i]表示i这个点被更新的次数,那 ...

  8. 时光机 (spfa判断负环)

    cnt数组记录每个点入栈次数,无负环时最大入栈次数为n,因为最短路最多有n-1条边. 有负环时最短路趋于负无穷,入栈次数大于n. #include<stdio.h> #include< ...

  9. Wormholes 虫洞 BZOJ 1715 spfa判断负环

    John在他的农场中闲逛时发现了许多虫洞.虫洞可以看作一条十分奇特的有向边,并可以使你返回到过去的一个时刻(相对你进入虫洞之前).John的每个农场有M条小路(无向边)连接着N (从1..N标号)块地 ...

最新文章

  1. 利用 jquery 获取某个元素下的所有图片并改变其属性
  2. 为什么我喜欢Spring bean别名
  3. MC.9 与 LIS
  4. Codeforces Round #304 (Div. 2) D. Soldier and Number Game 数学 质因数个数
  5. 利用NLB建立双机负载均衡群集
  6. JAVA 使用Jacob调用windows的Sapi实现文本转语音文件
  7. 【clickhouse】Clickhouse 版本号历史
  8. this.scrollheight获取textarea的高度是0_53小米电子时钟/v1.0 介绍
  9. PowerBuilder制作纸牌游戏
  10. 【文献翻译】基于CVSS的IT系统网络安全风险定量评估方法-A Quantitative CVSS-Based Cyber Security Risk Assessment Methodology
  11. 940mx黑苹果驱动_黑苹果 Clover 驱动配置文件分享
  12. 鼠标经过变成小手/箭头
  13. 微信小程序调用地图和跟据经纬度打开手机地图导航
  14. 【Alpha】Scrum Meeting 5
  15. 清华大学百年校庆给清华大学的一封信
  16. 深度学习——Dual Regression Networks for Single Image Super-Resolution(DRN)
  17. trinity运行原理及常见报错(一)
  18. 以后看电影就按这个名单了
  19. new String[0]的作用
  20. 《一个人的朝圣》读书摘记

热门文章

  1. 最大功率28W,高通新一代快充技术QC4.0曝光
  2. 《为自己工作——世界顶级设计师成功法则》—第1章1.7节平衡
  3. 二叉查找树(二叉排序树)创建,插入,删除操作。
  4. 软件测试之三——路径覆盖
  5. Linux知识点记录
  6. nfs服务器安装与客户端安装
  7. 骁龙617 android7,骁龙617手机有哪些?骁龙617手机汇总
  8. phpstudy php日志,phpstudy开启网站Apache日志并且按照日期划分创建
  9. apache 提示You don't have permission to access /test.php on this server.怎样解决
  10. activeMQ安装9(window下)