众所周知,SPFA可以判负环。如果采用BFS,那么存在负环的充要条件就是一个点入队超过总点数次。但不难看出,这样的方法效率是很低的。
我们考虑DFS。
如果题目只要求判断负环,我们便有一种效率稍高的方法:将dis数组初始化为0,对每个点跑一遍dfs即可,如果能在一次搜索中搜到重复的点,那么负环就存在。
#include<bits/stdc++.h> using namespace std; #define MAXN 2000000+10 typedef long long LL; struct ed{int v,next;LL w;}edge[MAXN*2]; int n,m,tot,head[MAXN],vis[MAXN]; bool flag=false; LL dis[MAXN]; void add(int u,int v,LL w){ edge[++tot].v=v; edge[tot].w=w; edge[tot].next=head[u]; head[u]=tot; } void dfs(int u){ if(flag)return; vis[u]=1; for(int i=head[u];i;i=edge[i].next){ int v=edge[i].v; if(flag)return; if(dis[u]+edge[i].w<dis[v]){ dis[v]=dis[u]+edge[i].w; if(vis[v]){ flag=true; return; } else dfs(v); } } vis[u]=0; } void init(){ tot=0; memset(head,0,sizeof(head)); memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); } int main(){ int T; scanf("%d",&T); while(T--){ init(); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v;LL w; scanf("%d%d%lld",&u,&v,&w); add(u,v,w); if(w>0)add(v,u,w); } flag=false; for(int i=1;i<=n;i++){ dfs(i); if(flag)break; } puts(flag?"YES":"NO"); } return 0; }