SPAF(虽然已经死了)判断负环—(大学复健第二篇)

SPAF判断负环存在其实就是bellman-fold的优化,加了一个队列来判断是否需要松弛操作。而判断负环上其实由于如果存在那么一定会有边被多次访问,而一定有负环的时候,访问数一定会超过n。于是我们可以得到一个简单的判断负环的算法。(猜猜看是哪个蠢蛋居然写不出来,错了十多遍o(╥﹏╥)o)

洛谷的判断负环

由于官方一直在更新数据,以前的代码居然被卡了一个数据点

#include <bits/stdc++.h>
using namespace std;

int T;
struct edge{
	int to,nex;
	int val;
}e[9009];int tot;
long long dis[4009];
bool vis[4009];
int cnt[4009];
int first[4009];
queue<long long>q;
inline int kd(){
	int x=0,f=1;char ch=getchar();
	while(isdigit(ch)==false){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)==true){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}

void add_edge(int a,int b,int c){
	e[++tot].to=b;
	e[tot].val=c;
	e[tot].nex=first[a];
	first[a]=tot;
}

int main(){
	cin>>T;
	while(T--){
		tot=0;
		int n=kd(),m=kd();
		memset(first,0,sizeof(first));
		memset(e,0,sizeof(e));
		for(int i=1;i<=m;i++){
			int a=kd(),b=kd(),c=kd();
			if(c>=0)add_edge(b,a,c);
			add_edge(a,b,c);
		}
		memset(dis,0x3f3f3f3f,sizeof(dis));
		memset(cnt,0,sizeof(cnt));
		memset(vis,0,sizeof(vis));
		
		q.push(1);
		vis[1]=true;
		cnt[1]++;
		dis[1]=0;
		int pan=false;
		while(q.empty()==false){	
			int now=q.front();
			q.pop();
			vis[now]=false;
			for(int i=first[now];i;i=e[i].nex){
				int to=e[i].to;
				if(dis[now]+e[i].val<dis[to]){
					dis[to]=dis[now]+e[i].val;
					cnt[to]=cnt[now]+1;
					if(vis[e[i].to]==false){
						q.push(to);
						vis[to]=true;
					}
					if(cnt[to]>n){
						puts("YES");
						pan=true;
						break;
					}
				}
			}
			if(pan==true)break;
		}
		if(pan==false)puts("NO");
		while(q.empty()==false)q.pop();
	}
} 

posted @ 2023-03-09 15:10  nono_ttaa  阅读(36)  评论(0编辑  收藏  举报