判定负环,用spfa的方法。设一个cnt数组,cnt[x]记录1~x最短路径包含的点数(石映奇dalao说的),如果大于了n那么表示他有负环了。如果正常跑完spfa,则表示没有负环。算法取了个巧,就是把负边的起点先加进来。
#include<cstdio>
#include<iostream>
#include<set>
#include<queue>
#include<cstring>
using namespace std;
const int N = 6005;
int T,head[N],ecnt;
int n,m,s;
int dis[N],cnt[N];
bool vis[N];
struct Edge {
int nxt,to,val;
} e[N<<2];
void add(int bg,int ed,int val) {
e[++ecnt].nxt=head[bg],e[ecnt].to=ed,e[ecnt].val=val,head[bg]=ecnt;
}
queue<int>q;
bool spfa() {
memset(cnt,0,sizeof cnt);
memset(vis,0,sizeof vis);
memset(dis,0x3f,sizeof dis);
q.push(s);
dis[s]=0;
vis[s]=1;
while(!q.empty()) {
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u]; i; i=e[i].nxt) {
int v=e[i].to;
if(dis[v]>dis[u]+e[i].val) {
if(!vis[v]) {
q.push(v);
vis[v]=1;
}
dis[v]=dis[u]+e[i].val;
cnt[v]=cnt[u]+1;
if(cnt[v]==n)return 0;
}
}
}
return 1;
}
int main() {
cin>>T;
while(T--) {
scanf("%d%d",&n,&m);
s=-1;
ecnt=0;
memset(head,0,sizeof head);
int a,b,c;
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&a,&b,&c);
if(c<0) s=a;
add(a,b,c);
}
if(s==-1){
cout<<"YE5\n";continue;
}
if(!spfa()) cout<<"YE5\n";
else cout<<"N0\n";
}
}
%%%zyj

4266

被折叠的 条评论
为什么被折叠?



