MARK 用spfa判断是否存在负环

判断是否存在负环的方法有很多,

其中用spfa判断的方法是:如果存在一个点入栈两次,那么就存在负环。

细节想想确实是这样,按理来说是不存在入栈两次的如果边权值为正的话

这个算法是O(N*M)

还有一种方法是直接用bellman-ford,虽说spfa也就是bellman-ford+FIFO队列

而且bellman-ford还可以计算负环的值

顺手附上代码好了:

for(int i=0;i<n;i++) d[i]=INF;//初始化
d[0]=0; for(int k=0;k<n-1;k++)//迭代n-1次,目前不懂为什么
for(int i=0;i<m;i++){//检查每条边
int x=u[i],y=v[i];
if(d[x]<INF) d[y]<?=d[x]+w[i];
}

这一题我是没有用bellman-ford...因为看到有人说用这个超时了= =

这里说一下用spfa的做法= =

虽然本蒟蒻第6个点莫名WA,但是毕竟思路还是正确的,自己MARK一下

目测是一些地方没有考虑到吧,据说有重边?有可能是这个?= =懒得管了

其实就是每个点都spfa一遍,看是否存在负环;

如果不存在的的话,就输出s-这些点的距离

至于spfa里面,其实也很简单,就是

	while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(dist[v]>dist[u]+e[i].w){
dist[v]=dist[u]+e[i].w;
if(!vis[v]){
vis[v]=true;
q.push(v);
if(ans[v]<2){//这里用数组ans记录下,v这个点入栈几次
ans[v]++;
}
else return true;
}
}
}
}

附上完整代码:

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxn=101000;
int n,m,k,t,x,y,s,z,tot=0;
struct edge{
int from,to,w,next;
}e[1010000];
int head[maxn],dist[maxn],ans[maxn];
bool vis[maxn];
int f[maxn];
bool flag;
void add(int x,int y,int z){
e[tot].from=x;
e[tot].to=y;
e[tot].w=z;
e[tot].next=head[x];
head[x]=tot++;
}
bool spfa(int s){
queue<int>q;
memset(dist,63,sizeof(dist));
memset(vis,false,sizeof(vis));
memset(ans,0,sizeof(ans));
q.push(s);
dist[s]=0;
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to;
if(dist[v]>dist[u]+e[i].w){
dist[v]=dist[u]+e[i].w;
if(!vis[v]){
vis[v]=true;
q.push(v);
if(ans[v]<2){
ans[v]++;
}
else return true;
}
}
}
}
return false;
}
int main(){
freopen("data.txt","r",stdin);
scanf("%d%d%d",&n,&m,&s);
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
if(x==y && z<0){
printf("-1\n");
return 0;
}
}
for(int i=1;i<=n;i++){
if(spfa(i)){
printf("-1\n");
return 0;
}
}
spfa(s);
for(int i=1;i<=n;i++){
if(dist[i]>1000000){
if(i!=s) printf("NoPath\n");
else printf("0\n");
}
else printf("%d\n",dist[i]);
}
return 0;
}

vijos1053 用spfa判断是否存在负环的更多相关文章

  1. poj3259 Wormholes【Bellman-Ford或 SPFA判断是否有负环 】

    题目链接:poj3259 Wormholes 题意:虫洞问题,有n个点,m条边为双向,还有w个虫洞(虫洞为单向,并且通过时间为倒流,即为负数),问你从任意某点走,能否穿越到之前. 贴个SPFA代码: ...

  2. POJ 3259 Wormholes(最短路,判断有没有负环回路)

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 24249   Accepted: 8652 Descri ...

  3. POJ 3259 Wormholes(bellman_ford,判断有没有负环回路)

    题意:John的农场里field块地,path条路连接两块地,hole个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts.我们的任务是知道会不会在从某块地出发后又回来,看到了离开之前 ...

  4. uva558 Wormholes SPFA 求是否存在负环

    J - Wormholes Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Stat ...

  5. poj3259Wormholes (Bellman_Ford/SPFA/Floyed算法判断是否存在负环)

    题目链接:http://poj.org/problem?id=3259 题目大意:一个图,有n个顶点,其中有m条边是双向的且权值为为正,w条边是单向的且权值为负,判断途中是否存在负环,如果有输出YES ...

  6. 使用spfa算法判断有没有负环

    如果存在最短路径的边数大于等于点数,就有负环 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数. 请你判断图中是否存在负权回路. 输入格式 第一行包含整数n和m. 接下来m行每行 ...

  7. POJ 1151 Wormholes spfa+反向建边+负环判断+链式前向星

    Wormholes Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 49962   Accepted: 18421 Descr ...

  8. bellman-ford算法(判断有没有负环)

    #include <iostream> #include <vector> #include<string> #include<cstring> usi ...

  9. spfa算法及判负环详解

    spfa     (Shortest Path Faster Algorithm) 是一种单源最短路径的算法,基于Bellman-Ford算法上由队列优化实现. 什么是Bellman_Ford,百度内 ...

随机推荐

  1. c语言获取符号位整数和浮点

    1. 为什么你应该得到的签位 非常多的时间,我们需要推断的数目值正和负,做了相应的逻辑处理.完成这一要求条件推断语句可以很好. 有时会出现以下情况, if (x > 0) { x = x - 1 ...

  2. c++的string容器

    c++相比c的一个好处就是实现了很多的容器和泛型算法,使得程序员的工作得到了很大的化简.其中一个很有用的泛型容器就是string.string是一个类,是一个在STL里边实现好了的类,由于他的很多功能 ...

  3. crawler_如何从页面获取新浪cookie

    步奏如下: 1 用chrome浏览器(其他浏览器原理相同)打开地址: http://weibo.com/ 2.点击鼠标右键 右键点击查看元素 点击Network   3.输入用户名  密码 执行登录 ...

  4. java-新浪微博开放平台——话题跟踪

    代码 网盘地址:http://pan.baidu.com/s/1pJ1D0Kz

  5. mysql 的load data infile要使用

    LOAD DATA INFILE从文本文件中读出的声明以极高的速度到表. 1.基本语法 LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'fi ...

  6. C语言第11课

    主要内容:函数指针 一.函数指针定义 int  maxValue(int  a,int  b) { return   a > b ? a : b; } 函数名和数组名一样是地址,存在在代码区 i ...

  7. 瘸腿蛤蟆笔记29-cocos2d-x-3.2 Box2d物理引擎dynamics模块介绍

    转载标明出处:http://blog.csdn.net/notbaron/article/details/38611335 上篇回想 本篇名言:奋斗.寻觅.发现,而不屈服.[诗人丁尼生] 上篇中,我们 ...

  8. C# 根据年、月、周、星期获得日期等

    原文:C# 根据年.月.周.星期获得日期等 /// 取得某月的第一天 /// </summary> /// <param name="datetime">要 ...

  9. QT最简单的程序执行过程分析(内含C++基础知识)

    打开QT Creator,新建一个“应用程序-Qt Widgets Application”项目: 输入名称scdc之后点击下一步. 在“构建套件”这个页面中直接点出下一步,然后再输入自己的类名Dat ...

  10. Asp.net Identity 系列之 怎样修改Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的 Id 字段的数据类型

    这篇博客我们来学习如何将AspNetUsers 表的Id 字段 的类型由nvarchar(128) 改为Int 并且子增长 1.为什么要修改 如果你运行过 Asp.net mvc 示例项目,你好会发现 ...