/*
* Problem :: 1865 / 웜홀
*
* Kind :: Bellman-Ford
*
* Insight
* - 한 지점에서 출발을 하여서 시간여행을 하기 시작하여
* 다시 출발을 하였던 위치로 돌아왔을 때,
* 출발을 하였을 때보다 시간이 되돌아가 있는 경우가 있는지 없는지
* + 음수의 사이클이 있는지 없는지
* # 벨만포드 알고리즘을 적용하자
*
* - 다익스트(Dijkstra)는 간선의 가중치가 모두 0 또는 양수이므로
* 다익스트라 알고리즘을 적용해서 최단거리르 구하는 도중,
* 아직 방문하지 않은 상태인 모든 노드들 중 출발점으로부터의 거리가 제일 짧은 노드가
* 출발점으로부터 그 노드까지의 최단거리가 된다
* + 하지만 간선들 중 하나라도 가중치가 음수인 간선이 있다면,
* 아직 방문하지 않은 상태인 모든 노드들 중 출발점으로부터의 거리가 제일 짧은 노드가
* 출발점으로부터 그 노드까지의 최단거리가 아닐 수도 있다!
* # (u,v:t) = u번 노드 -> v번 노드, 거리 t 라면
* (1,2:1), (2,3:2) 로 1->2->3 인 (1,3:3) 이 최단거리인줄 알았으나
* (2,4:3), (4,3:-2) 로 1->2->4->3 인 (1,3:2) 이 실제 최단거리일 수 있다
* => 때문에, 최단거리를 구하는 도중 어떤 노드가 현재 최단거리인지 알 수 없고
* 결국 모든 경우의 수를 따져봐야 한다
*
* - N 개의 노드가 있다면 가능한 최단거리는 (N-1)개의 간선으로 이루어진다
* 모든 경우의 수를 따지려면, 모든 간선을 (N-1)번 Relaxation 해야한다
* 즉, 모든 간선을 한번 순회하며 Relaxation 하고
* 한 번이라도 Relaxation 이 일어났다면, 모든 간선을 다시 순회하며 Relaxation 하고
* 또 한 번이라도 Relaxation 이 일어났다면, 모든 간서을 다시 순회하며 Relaxation 하고...
* 이렇게 (N-1)번 반복해야 한다
* + 게산이 끝나면 "음의 사이클이 없는 한" 현재 계산된 각 노드별 최단거리가 실제 최단거리이다
* 하지만 여기서 모든 간선을 다시 한번 순회하며 Relaxation 해준다
* 음의 사이클이 있는지 확인하기 위해서이다
* # 만약, 여기서 Relaxation 이 한 번이라도 일어난다면,
* 음의 사이클이 존재한다는 뜻이다
* N 개의 간선으로 이루어진 최단거리가 존재한다는 뜻이기 때문이다!
* 즉, 중복된 간선이 있다는 뜻이고 간선이 중복되기 위해서는 사이클이 있어야 하기 때문에
* 이 사이클은 음의 사이클일 수밖에 없다
* => 종합하자면, 모든 간선을 (N-1)번 순회하며 Relaxation 해주고
* 한번 더 모든 간선을 순회하며 Relaxation 해줌으로써
* Relaxation 이 일어나는지 여부로 음의 사이클의 존재 여부를 알 수 있다
*
* Point
* - 본 코드에서는 s=시작점, e=도착점, t=걸리는시간 을 뜻하는데,
* Relaxation 조건을 if (D[s] + t < D[e]) 가 아닌
* if (D[s] != INF && D[s] + t < D[e]) 로 주면 <= 시작점이 INF 인지 확인하는 조건 추가
* s == e, t < 0 일 때의 음의 사이클을 확인하지 못하게 되어 틀리게 된다
*
* - 오랜만이라 그런지 다익스트라, 벨만포드 둘 다 기억이 나질 않네... ㅎㅎ
* + 꾸준히 복습하고 기록하자~
*/
//
// BOJ
// ver.C++
//
// Created by GGlifer
//
// Open Source
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define endl '\n'
// Set up : Global Variables
struct Edge { int s, e, t; };
#define INF (int)(1e9+7)
// Set up : Functions Declaration
/* None */
int main()
{
// Set up : I/O
ios::sync_with_stdio(false);
cin.tie(nullptr);
// Set up : Input
int TC; cin >> TC;
while (TC--) {
int N, M, W;
cin >> N >> M >> W;
vector<Edge> E;
for (int i=0; i<M; i++) {
int s, e, t;
cin >> s >> e >> t;
E.push_back({s, e, t});
E.push_back({e, s, t});
}
for (int i=0; i<W; i++) {
int s, e, t;
cin >> s >> e >> t;
E.push_back({s, e, -t});
}
// Process
int D[N+1];
fill(&D[1], &D[N+1], INF);
D[1] = 0;
for (int i=0; i<N-1; i++) {
for (Edge edge : E) {
auto [s, e, t] = edge;
if (D[s] + t < D[e]) {
D[e] = D[s] + t;
}
}
}
bool isPossible = false;
for (Edge edge : E) {
auto [s, e, t] = edge;
if (D[s] + t < D[e]) {
isPossible = true;
break;
}
}
// Control : Output
cout << ((isPossible) ? "YES" : "NO") << endl;
}
}
// Helper Functions
/* None */