题意:一个图,有一些“正常”的点和边(废话),点表示农场的位置、边表示从一个农场到另一个农场花费的时间。打住。还有些特别的点(虫洞),这些特别的点和其他点的边代表着能“穿越”的时间。问:有没有可能从虫洞穿越到某个点,时间倒流。
这个模型就是把正常的点互相连接起来或者把正常的点到虫洞,权是正。但是虫洞到其他的点,权为负。建立一个存在负权的图,然后最最最最关键的就是:判断是否存在负权回路。单源最短路算法里面正好bellman-ford可以处理负权,而且算法的返回值就是一个bool型的量,用来反映是不是存在负权回路了
/*
Sample Input
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
Sample Output
NO
YES
*/
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#define MAXVN 520
#define MAXEN 6000
#define INF 1000000000
using namespace std;
int dis[MAXVN], ispushed[MAXVN], pushtimes[MAXVN];
typedef struct{
int v, value;
}Edge;
int vn, en;
typedef vector<Edge> VE;
VE eg[MAXVN];
queue<int> Q;
int spfa(int st){
memset(ispushed, 0, sizeof(ispushed));
memset(pushtimes, 0, sizeof(pushtimes));
for(int i = 1;i <= vn; i++) dis[i] = INF;
dis[st] = 0;
while(!Q.empty()) Q.pop();
Q.push(st); ispushed[st] = 1;
pushtimes[st]++;
while(!Q.empty()){
int be = Q.front();
Q.pop(); ispushed[be] = 0;
for(int i = 0; i < eg[be].size(); i++){
if(dis[eg[be][i].v] > dis[be] + eg[be][i].value){
dis[eg[be][i].v] = dis[be] + eg[be][i].value;
if(!ispushed[eg[be][i].v]){
Q.push(eg[be][i].v);
ispushed[eg[be][i].v] = 1;
pushtimes[eg[be][i].v]++;
if(pushtimes[eg[be][i].v] >= vn+1) return 1;
}
}
}
}
return 0;
}
int main(){
int t, n, m, w,a, b, c;
while(scanf("%d", &t) != EOF){
while(t--){
for(int i = 1; i <= vn; i++) eg[i].clear();
scanf("%d%d%d", &n, &m ,&w);
vn = n;
while(m--){
scanf("%d%d%d", &a, &b, &c);
Edge tmp;
tmp.v = b;
tmp.value = c;
eg[a].push_back(tmp);
tmp.v = a;
eg[b].push_back(tmp);
}
while(w--){
scanf("%d%d%d", &a, &b, &c);
Edge tmp;
tmp.v = b;
tmp.value = 0 - c;
eg[a].push_back(tmp);
}
if(spfa(1)) printf("YES\n");
else printf("NO\n");
}
}
}