#include using namespace std; //这里的M取值需要总结一下,因为有100组以下的输入,所以还需要乘以100,才是真正的边数上限 const int N = 110, M = N * N * 100; //邻接表 int e[M], h[N], idx, w[M], ne[M]; void add(int a, int b, int c) { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; } int d[N]; //最短距离数组 bool st[N]; //是不是进过队列 int cnt[N]; int n, m, T; bool spfa(int start) { //求最长路,所以判断正环 queue q; //有时候换成栈判断环很快就能 //差分约束从超级源点出发 d[start] = 0; q.push(start); st[start] = true; while (q.size()) { int t = q.front(); q.pop(); st[t] = false; for (int i = h[t]; ~i; i = ne[i]) { int j = e[i]; if (d[j] > d[t] + w[i]) { //求最短路 d[j] = d[t] + w[i]; cnt[j] = cnt[t] + 1; //注意多加了超级源点到各各节点的边 if (cnt[j] >= n + 1) return false; if (!st[j]) { q.push(j); st[j] = true; } } } } return true; } int main() { cin >> T; while (T--) { cin >> n >> m; memset(h, -1, sizeof h); memset(d, 0x3f, sizeof(d)); memset(cnt, 0, sizeof(cnt)); memset(st, 0, sizeof(st)); while (m--) { int s, t, v; cin >> s >> t >> v; //这里c本身就是前缀的结果,不需要我们另外计算前缀和 add(t, s - 1, -v), add(s - 1, t, v); } //建立超级源点 for (int i = 1; i <= n; i++) add(n + 1, i, 0); //整条路径中存在负环,意味着不等式组存在矛盾 if (!spfa(n + 1)) cout << "false" << endl; else cout << "true" << endl; } return 0; }