​传送门​​​ 题意:艾高比较差QAQ。意思是农夫发现了虫洞,他发现从一个点到另一个点会花费一些时间,存在一些点到点可以到退时间。问farm是否可以通过一个回路回到过去。就是问是否存在一条负权的边。
思路:spfa判断负环模板即可,要注意,有些虫洞是可以来回的,所以一条边要添加两次(题目中给出,是双向路径)。
(既然有负边权为什么还会存在no呢,因为可能出现0边权,这样一来,负边权就不会无限更新了)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 100100, INF = 0xfffffff;
int head[maxn], vis[maxn], d[maxn];
int n, m;
int in[maxn];
struct node {
int u, v, d, next;
} Node[maxn];
void add(int u, int v, int d, int i) {
Node[i].u = u;
Node[i].v = v;
Node[i].d = d;
Node[i].next = head[u];
head[u] = i;
}

bool spfa(int s) {
mem(d, 0x3f);
d[s] = 0;
mem(vis, 0);
mem(in, 0);
queue<int> Q;
Q.push(s);
vis[s] = 1;
in[s] = 1;
while(!Q.empty()) {
int u = Q.front();
Q.pop();
vis[u] = 0;
for(int i = head[u]; i != -1; i = Node[i].next) {
node e = Node[i];
if(d[e.v] > d[u]+e.d) {
d[e.v] = d[u]+e.d;
if(!vis[e.v]) {
Q.push(e.v);
vis[e.v] = 1;
in[e.v]++;
if(in[e.v] > n)
return 1;
}
}
}
}
return 0;
}

int main() {
int T;
cin >> T;
int x;
while(T--) {
mem(head, -1);
cin >> n >> m >> x;
int ans = 0;
int u, v, d;
for(int i = 1; i <= m; i++) {
cin>>u>>v>>d;
add(u, v, d, ans++);
add(v, u, d, ans++);
}
while(x--) {
cin >> u >> v >> d;
add(u, v, -d,ans++);
}
if(spfa(1))
cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}