负环模板
负环模板
时间复杂度:\(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;
}

浙公网安备 33010602011771号