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. Unity3D的SerializeField 序列化域名

    SerializeField Inherits from Attribute Force Unity to serialize a private field. 强制Unity去序列化一个私有域. Y ...

  2. Saving HDU (贪心)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2111 好久不刷题,拿到水题切了切,,,,,题意刚开始都没有理解,,,,真是弱了,,,, 简单贪心,,, ...

  3. hdu To and Fro

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1200 代码: #include <stdio.h> #include <string ...

  4. android登录界面

    在网上在到一个登录界面感觉挺不错的,给大家分享一下~先看效果图: 这个Demo除了按钮.小猫和Logo是图片素材之外,其余的UI都是通过代码实现的. 一.背景 背景蓝色渐变,是通过一个xml文件来设置 ...

  5. JavaScript闭包的一些理解

    原文:JavaScript闭包的一些理解 简单一点的说:闭包就是能够读取其他函数内部变量的函数.那如何实现读取其它函数内部变量呢,大家都知道在JavaScript中内部函数可以访问其父函数中的变量,那 ...

  6. Swift中文教程(三)--流程控制

    原文:Swift中文教程(三)--流程控制 Swift用if和switch编写条件控制语句,用for-in,for,while和do-while编写循环.条件控制语句和循环语句中,小括号是可选的,但花 ...

  7. 归并排序 & 快速排序

    归并排序 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有 ...

  8. Redis 3.0集群搭建/配置/FAQ

    ·声明 1,已官网中文教程为基础,边看边学,结合环境现状搭建. 2,哥对Ruby不热爱.不熟悉.不感冒,所述内容如有疑义请谅解. 3,3.0官说集群还在测试中,其实用用也还算马马虎虎,对外集群API真 ...

  9. MyEclipse 设置全部jsp的编码为UFT-8 的方法

  10. 第1章3节《MonkeyRunner源码剖析》概述:架构(原创)

    天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文“寻求合作伙伴编写<深入理解 MonkeyRunner>书籍“.但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在 ...