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();
}
}