负环模板

题目

负环模板

时间复杂度:\(O(Tnm)\)

#include<bits/stdc++.h>
using namespace std;
const int N=3005;
int T,n,m,hd[N],ver[2*N],nxt[2*N],w[2*N],tot,dis[N],cnt[N];//cnt:从起点到该点的最短路径边数
bool vis[N];//标记节点是否在队列中
queue<int> q;
void add(int u,int v,int c){
	ver[++tot]=v;w[tot]=c;nxt[tot]=hd[u];hd[u]=tot;
}
bool SPFA(){//SPFA判断从1出发能否到达负环
	memset(dis,0x3f,sizeof(dis));//初始化
	memset(vis,0,sizeof(vis));
	memset(cnt,0,sizeof(cnt));
	dis[1]=0;q.push(1);
	while(q.size()){
		int u=q.front();q.pop();
		vis[u]=false;
		for(int i=hd[u];i;i=nxt[i]){//遍历u的所有出边
			int v=ver[i];
			if(dis[v]>dis[u]+w[i]){
				dis[v]=dis[u]+w[i];
				cnt[v]=cnt[u]+1;//更新路径边数
				if(cnt[v]>=n) return true;//边数≥n,必有负环
				if(!vis[v]){//如果v不在队列中,则入队
					q.push(v);
					vis[v]=true;
				}
				
			}
		}
	}
	return false;//未发现负环
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);
	cin>>T;
	while(T--){
		tot=0;memset(hd,0,sizeof(hd));//清空图
		cin>>n>>m;
		for(int i=1,u,v,c;i<=m;i++){
			cin>>u>>v>>c;
			add(u,v,c);
			if(c>=0) add(v,u,c);
		}
		//题目要求只考虑从1出发能到达的负环,所以SPFA起点为1
		if(SPFA()) cout<<"YES\n";
		else cout<<"NO\n";
	}
	return 0;
}
posted @ 2026-08-12 11:52  decentz  阅读(9)  评论(0)    收藏  举报