思路:
(1)负环:区别于正环,在求最短路过程中,正环会绕路,故不会被讨论,而负环会不断让路总权更短,会让算法不断循环;
(2)于是考虑统计spfa最短路算法走过的路径数,如果路径数超过合理值n - 1,说明必然存在负环;
(3)于是对spfa算法做适当修改,
- 一方面为防止1到不了负环,于是率先将所有点都提前放进队列中;
- 另一方面在更新距离时统计该路径边数;
- 由于只要存在负环,就会不断循环,所以无需将dist[]初始化。
代码:
#include<bits/stdc++.h>using namespace std;const int N = 150000;int n,m;
int h[N],st[N],e[N],ne[N],idx,dist[N],w[N],cnt[N];void add(int a,int b,int c)
{e[idx] = b,ne[idx] = h[a],w[idx] = c,h[a] = idx ++;
}bool spfa()
{queue<int> q;for(int i = 1;i <= n;i ++) {q.push(i);st[i] = 1;}while(!q.empty()){auto t = q.front();q.pop();st[t] = 0;for(int i = h[t];i != -1;i = ne[i]){int j = e[i];if(dist[j] > dist[t] + w[i]){dist[j] = dist[t] + w[i];cnt[j] = cnt[t] + 1;if(cnt[j] >= n) return true;if(!st[j]){q.push(j);st[j] = 1;}}}}return false;}int main()
{memset(h,-1,sizeof h);cin >> n >> m;while(m --){int a,b,c;cin >> a >> b >> c;add(a,b,c);}if(spfa()) printf("Yes");else puts("No");return 0;
}