鉴于《飞离地球》这个坑货用到了SPFA,我痛定思痛复习SPFA
每次取队首,遍历与之相同的节点,查询对比 dis [ y ] 与 dis [ x ] + len ( x , y )
感谢 Y.YL dalao(边权大于等于0时是双向边)原题粘过来也不能A啊啊啊
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
int dist[N], cnt[N],ne[N], h[N], e[N], w[N], idx = 0;
bool st[N];
void add(int a, int b, int c) {
e[idx] = b;
w[idx] = c;
ne[idx] = h[a];
h[a] = idx++;
}
int spfa() {
memset(dist, 0x3f, sizeof dist);
queue<int> q;
for (int i = 1; i <= n; i++) { //从1开始并不一定能找到负环
st[i] = 1;
q.push(i);
}
while (q.size()) {
int 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 1;
if (!st[j]) {
st[j] = 1;
q.push(j);
}
}
}
}
return 0;
}
int main() {
int t;
scanf("%d",&t);
while(t --) {
memset(h, -1, sizeof h);
memset(cnt, 0, sizeof cnt);
memset(st, 0, sizeof st);
scanf("%d%d",&n,&m);
for (int i = 0; i < m; i++) {
int u,v,w;
scanf("%d%d%d", &u,&v,&w);
add(u,v,w);
if(w >= 0) add(v,u,w);
}
if(spfa()) puts("YE5");
else puts("N0");
}
return 0;
}