【模板】负环判定

存在负环,即:执行 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;
}
posted @ 2019-03-16 22:11  shellpicker  阅读(188)  评论(0编辑  收藏  举报