【模板】负环判定

存在负环,即:执行 spfa 算法时,一个点被更新了 N 次或 N 次以上,那么一定存在负环。由于无向图任意两点间的简单路径经过的边数均小于 N,且 B-F 算法在第 i 轮迭代结束时可以求得经过不超过 i 条边得到的单源最短路。因此, 在 N-1 次迭代时一定可以将所有点的最短路均求出。
更高效率的做法是记录一个点最短路经过的边数,若边数大于等于了 N,则证明出现了负环。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxv=2010;
const int maxe=3010;

inline int read(){
    int x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}

struct node{
    int nxt,to,w;
}e[maxe<<1];
int tot=1,head[maxv];
inline void add_edge(int from,int to,int w){
    e[++tot]=node{head[from],to,w},head[from]=tot;
}

int n,m,d[maxv],cnt[maxv];
bool in[maxv];

bool spfa(){
    queue<int> q;
    memset(d,0x3f,sizeof(d));
    memset(in,0,sizeof(in));
    d[1]=0,in[1]=1,q.push(1);
    while(q.size()){
        int u=q.front();q.pop(),in[u]=0;
        if(cnt[u]>=n)return 1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].to,w=e[i].w;
            if(d[v]>d[u]+w){
                d[v]=d[u]+w,cnt[v]=cnt[u]+1;
                if(!in[v])q.push(v),in[v]=1;
            }
        }
    }
    return 0;
}

void read_and_parse(){
    n=read(),m=read();
    for(int i=1,x,y,z;i<=m;i++){
        x=read(),y=read(),z=read();
        if(z>=0)add_edge(x,y,z),add_edge(y,x,z);
        else add_edge(x,y,z);
    }
}

void solve(){
    puts(spfa()?"YE5":"N0");
}

void init(){memset(head,0,sizeof(head)),memset(cnt,0,sizeof(cnt)),tot=1;}

int main(){
    int T=read();
    while(T--){
        init();
        read_and_parse();
        solve();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wzj-xhjbk/p/10544632.html
今日推荐