【洛谷P3385】【模板】负环

题目大意

给你一个图,判断有没有负环。

分析

判断负环我们一般用spfa,spfa判断负环有两种实现方法,一种是基于bfs,一种是基于dfs。

关于spfa,有篇国家集训队论文,姜碧野的《SPFA算法的优化及应用》。

知乎上有一个spfa讲的不错的,地址

就是说基于dfs的spfa判负环要比基于bfs的要快,但是基于bfs的比基于dfs的求最短路要快。这也就是dfs和bfs的各自特点所形成的。

代码

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=200005;
inline void read(int &x){
    bool flag=0; x=0; char ch=getchar();
    while(ch<'0'||ch>'9'){flag=(ch=='-');ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    x=flag?~x+1:x;
}
int n,m,T,tot;
int head[maxn],dis[maxn]; bool vis[maxn];
struct node{
    int next,to,dist;
}e[maxn<<1];
inline void ins(int from,int to,int dist){
    e[++tot].next=head[from];
    e[tot].to=to; e[tot].dist=dist;
    head[from]=tot;
}
bool spfa(int x){
    vis[x]=true;
    for(int i=head[x];i;i=e[i].next)
    if(dis[e[i].to]>dis[x]+e[i].dist){
        if(vis[e[i].to]) return true;
        dis[e[i].to]=dis[x]+e[i].dist;
        if(spfa(e[i].to)) return true;
    }
    return vis[x]=false;
}
int main(){
    read(T);
    while(T--){
        tot=0; memset(head,0,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
        read(n);read(m);
        for(int i=1;i<=m;++i){
            int a,b,w; read(a);read(b);read(w);
            ins(a,b,w); if(w>=0) ins(b,a,w);
        }
        bool flag=0;
        for(int i=1;i<=n;++i)
        if(spfa(i)){
            flag=true;
            break;
        }
        if(flag) printf("YE5\n");
        else printf("N0\n");
    }
        return 0;
}

 

posted @ 2017-10-30 20:06  沐灵_hh  阅读(330)  评论(0编辑  收藏  举报