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

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

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

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

http://poj.org/problem?id=3259

在探索他的许多农场时,农夫约翰发现了许多令人惊奇的虫洞。一个虫洞是非常奇怪的,因为它是一条单向的路径,在你进入虫洞之前的一段时间把你送到它的目的地!FJ的每个农场包括N(1≤)N≤500)方便地编号为1.NM(1≤)M(≤2500)路径,以及W(1≤)W≤200)虫洞。

由于FJ是一个狂热的时间旅行迷,他想做以下几件事:从某个领域开始,穿过一些路径和虫洞,然后在他最初离开之前回到起点。也许他能认识自己:)。

为了帮助FJ找出这是否可能,他会向你提供完整的地图F(1≤)F≤5)他的农场。任何路径都不会超过10,000秒的行程,而且没有虫洞能使FJ及时返回超过10,000秒。

输入

第1行:一个整数,FF农场的描述如下。
每个场的第1行:三个空格分隔的整数:NM,和W 
第2行.。M+一个农场:三个空格分隔的数字(SET)分别描述:双向路径SE这需要T再过几秒钟。两个字段可能由多条路径连接。
线M+2.. MW+一个农场:三个空格分隔的数字(SET)分别描述:从SE这也会让旅行者回来T几秒钟。

输出量

第1行.。F*对于每个农场,如果FJ能够实现他的目标,输出“是”,否则输出“否”(不包括引号)。

样本输入

2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8

样本输出

NO
YES

BFS_SPFA版:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
struct node {ll id;ll d;ll next_s;
}side[6000];
ll cnt,n,head[501],flag[501],dis[501],cn[501];
ll book;
void init(){memset(head,-1,sizeof(head));cnt=0;
}void add(ll x,ll y,ll z){side[cnt].id=y;side[cnt].d=z;side[cnt].next_s=head[x];head[x]=cnt++;
}ll bfs_spfa(){memset(cn,0,sizeof(cn));//cn[i]记录i入队的次数 memset(dis,INF,sizeof(dis));//初始化dis dis[1]=0;queue<ll> p;//压入那个点,看dis的含义 p.push(1);flag[1]=1;while(p.size()){ll t=p.front();p.pop();flag[t]=0;for(int i=head[t];i!=-1;i=side[i].next_s){if(dis[side[i].id]>dis[t]+side[i].d){dis[side[i].id]=dis[t]+side[i].d;if(!flag[side[i].id]){p.push(side[i].id);flag[side[i].id]=1;cn[side[i].id]++;//接下来和求单源最短路的不同的地方 if(cn[side[i].id]>=n){  //关键不能是大于,是大于等于或等于 return 1;}}}}}return 0;
}int main(){ll f;cin>>f;while(f--){memset(dis,INF,sizeof(dis));memset(flag,0,sizeof(flag));init();ll m,w;cin>>n>>m>>w;for(int i=0;i<m;i++){ll x,y,z;cin>>x>>y>>z;add(x,y,z);add(y,x,z);}for(int i=0;i<w;i++){ll x,y,z;cin>>x>>y>>z;add(x,y,z*(-1));}book=bfs_spfa();if(book==1){cout<<"YES"<<endl;}else cout<<"NO"<<endl;}return 0;
}

DFS_SPFA版:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
struct node {ll id;ll d;ll next_s;
}side[6000];
ll cnt,n,head[501],flag[501],dis[501],cn[501];
ll book;
void init(){memset(head,-1,sizeof(head));cnt=0;
}void add(ll x,ll y,ll z){side[cnt].id=y;side[cnt].d=z;side[cnt].next_s=head[x];head[x]=cnt++;
}void dfs_spfa(ll x){if(book)return ;flag[x]=1;for(int i=head[x];i!=-1;i=side[i].next_s){if(book)return ;if(dis[side[i].id]>dis[x]+side[i].d){dis[side[i].id]=dis[x]+side[i].d;if(!flag[side[i].id]){dfs_spfa(side[i].id);//side[i].id不在路径中,就继续扩展 }else {//如果side[i].id已经在路径上,则把book标记为1返回 book=1;return ;}}}flag[x]=0;
}int main(){ll f;cin>>f;while(f--){book=0;memset(dis,INF,sizeof(dis));memset(flag,0,sizeof(flag));init();ll m,w;cin>>n>>m>>w;for(int i=0;i<m;i++){ll x,y,z;cin>>x>>y>>z;add(x,y,z);add(y,x,z);}for(int i=0;i<w;i++){ll x,y,z;cin>>x>>y>>z;add(x,y,z*(-1));}dis[1]=0;dfs_spfa(1);if(book==1){cout<<"YES"<<endl;}else cout<<"NO"<<endl;}return 0;
}

SPFA算法判断负权环(bfs_spfa,dfs_spfa)相关推荐

  1. 差分约束系统之Bellman_Ford与Spfa判断负权回路

    题目:http://poj.org/problem?id=1364 题意:就是简单的差分约束模型. 分析:首先我们必须知道,如果图中存在负权回路,那么差分约束没有可行解.而存在负权回路的条件是:图中某 ...

  2. 图论 —— 环与块 —— 负权环

    [概述] 从一个点出发,经过一条简单路径回到起点,称为图的环,而图的负权环就是环中所有的边的权值均为负值. 所谓负权环问题,就是判断图中是否存在一个环,里面包含的边的边权总和<0 [Bellma ...

  3. AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)

    题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...

  4. 牛客OI周赛5-提高组 wpy的请求 (spfa变形求负权通路)

    wpy的请求 spfa变形 题目大意:给一个n个点,m条边的有向图,可能有负权边,现在要把负边权都变成非负, 并且使得原图中的任意两点u,v最短路经过路径不变并且使得原图中的任意两点u,v最短路经过路 ...

  5. 【最短路径问题笔记】SPFA算法及负环的判断

    dis数组:记录源点到每个结点最短路径值 in数组:记录结点进队次数 vis数组:记录结点是否在队列中 设立队列用来保存待优化的结点: 优化时每次取出队首结点cur,并且用cur点当前的最短路径对u点 ...

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

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

  7. spfa 判断负环 (转载)

    当然,对于Spfa判负环,实际上还有优化:就是把判断单个点的入队次数大于n改为:如果总的点入队次数大于所有点两倍 时有负环,或者单个点的入队次数大于sqrt(点数)有负环.这样时间复杂度就降了很多了. ...

  8. 单源最短路 SPFA 算法模板

    简介 在图论中,最短路是十分重要的一部分,在很多问题中都有涉及 而现在所讲的 SPFA 算法是十分优秀的算法,时间复杂度为 O(k∗E)O(k*E) 其中 EE 是图的边数,而 kk 是一个常数,一般 ...

  9. Spfa算法(可以求有负权的图)

    S p f a Spfa Spfa s p f a spfa spfa 通常用于求含负权边的单源最短路径,以及判负权环. s p f a spfa spfa 最坏情况下复杂度和朴素 B e l l m ...

最新文章

  1. ipad无法与itunes同步,提示因为这台电脑不再被授权使用在此ipad上购买的项目解决方案...
  2. 说一下你对多态的理解?_掌握了多态的特性,写英雄联盟的代码更少啦!
  3. BZOJ1217: [HNOI2003]消防局的设立
  4. spring order_Spring @Order批注
  5. c语言for循环++_C ++程序使用循环查找数字的幂
  6. 科研论文研读工具及英文论文写作
  7. 如何压缩PPT文档的大小
  8. 《植物大战僵尸(PC)》游戏评测
  9. 神经网络论文Enhancing deep neural networks via multiple kernel learning
  10. 马王堆汉墓帛书‧老子——甲本释文(德经)
  11. 华为云——开发者技能测评
  12. 【自然语言处理】详说中文自动分词
  13. VS2015 0xc000007b应用程序无法正常启动 解决办法
  14. 一张不错的国内网络安全法规方面立法的历程图
  15. 单调队列,单调栈总结
  16. “计算机程序设计能力考试(乙级)”真题刷题(三)
  17. [暑期第二阶段]8月19日~8月30日总结
  18. Windows 任意窗口置顶显示
  19. What is ESI?
  20. java之SimpleDateFormat日期格式化

热门文章

  1. C基础 | 【05】(内存结构以及复合类型)
  2. 启动(程序还没执行生成dump文件的代码)就崩溃的处理流程
  3. Ubuntu 小企鹅输入法fcitx 支持 五笔拼音
  4. 香港中文大学9(深圳)医学院李丛磊组招收博后/科研助理/博士生
  5. 低配本用win10服务器系统,低配电脑用win7还是win10比较好_低配置电脑装win7还是win10系统合适...
  6. AutoCAD关于选择的一些技巧(如何高效地框选)
  7. 【C语言】基础练习题
  8. ubuntu绘图软件
  9. C语言中无符号数和有符号数之间的比较和运算
  10. stm32检测串口空闲的原理