SPFA算法:
于是板子题又双叒叕应运而生:传送门
#include<bits/stdc++.h>
#define ff(i,s,e) for(int i=s;i<=e;i++)
#define fff(i,s,e) for(int i=s;i>=e;i--)
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch == '-') f=-1 ; ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48) ; ch=getchar();}
return x*f;
}
const int N=2010,M=3010,inf=0x3f3f3f3f;
int n,m;
int tal,head[N];
int dis[N];
int mark[N];//元素i被标记过几次
bool vis[N];//元素i是否在队列中
struct qwq{
int to,nxt,w;
}a[M*2];
queue<int> q;
void add(int u,int v,int w){//链式前向星存储
a[++tal].w=w;
a[tal].to=v;
a[tal].nxt=head[u];
head[u]=tal;
}
bool spf(){
ff(i,1,n) dis[i]=inf,vis[i]=0,mark[i]=0;//预处理
while(!q.empty()) q.pop();//清空队列
q.push(1);//将起点加入队列
dis[1]=0,vis[1]=1,mark[1]++;
while(!q.empty()){
int u=q.front();//取出队首元素
q.pop();
vis[u]=0;//标记队首出队
for(int i=head[u];i;i=a[i].nxt){//枚举u可到达的所有结点
int v=a[i].to;
if(dis[v]>dis[u]+a[i].w){//若以u为中转结点更优,更新
dis[v]=dis[u]+a[i].w;
if(!vis[v]){//若v不在队列,将其加入
vis[v]=1,mark[v]++;q.push(v);
}
if(mark[v]>=n) return 1;//判断负环,可由松弛原理推导
}
}
}
return 0;
}
int main(){
int T=read(),u,v,w;
while(T--){
n=read(),m=read();
tal=0;
memset(head,0,sizeof(head));//初始化
ff(i,1,m){
u=read(),v=read(),w=read();
add(u,v,w);
if(w>=0) add(v,u,w);
}
if(spf()) printf("YES\n");
else printf("NO\n");
}
return 0;
}
阿巴阿巴……