#include <bits/stdc++.h>
using namespace std;
constexpr int MIL = 1'000'000;
// Funkcje pomocnicze do mapowania indeksów
inline int edgeNode(int idx) { return idx; }
inline int prefixNode(int idx) { return MIL + idx; }
inline int suffixNode(int idx) { return 2 * MIL + idx; }
// Klasa do wykrywania cyklu w grafie skierowanym
struct CycleDetector {
vector<vector<int>>& graph;
vector<bool> visited, recStack;
CycleDetector(vector<vector<int>>& g) : graph(g) {
visited.assign(graph.size(), false);
recStack.assign(graph.size(), false);
}
bool dfs(int u) {
visited[u] = true;
recStack[u] = true;
for (int v : graph[u]) {
if (!visited[v] && dfs(v)) return true;
else if (recStack[v]) return true;
}
recStack[u] = false;
return false;
}
bool hasCycle() {
for (int i = 0; i < (int)graph.size(); i++)
if (!visited[i] && dfs(i))
return true;
return false;
}
};
// Funkcja budująca graf na podstawie wczytanych danych
void buildGraph(int n, int m,
const vector<vector<pair<int,int>>>& in,
const vector<vector<pair<int,int>>>& out,
vector<vector<int>>& graf) {
// Dodajemy krawędzie prefixowe i suffixowe
for (int i = 1; i <= n; ++i) {
graf[prefixNode(i)].push_back(edgeNode(i));
graf[suffixNode(i)].push_back(edgeNode(i));
}
for (int i = 1; i <= n; ++i) {
for (int j = 0; j + 1 < (int)out[i].size(); ++j) {
graf[prefixNode(out[i][j].second)].push_back(prefixNode(out[i][j + 1].second));
graf[suffixNode(out[i][j + 1].second)].push_back(suffixNode(out[i][j].second));
}
}
for (int i = 1; i <= n; ++i) {
int l = 0;
for (int j = 0; j < (int)in[i].size(); ++j) {
if (out[i].empty()) continue;
while (l < (int)out[i].size() && out[i][l].first < in[i][j].first) l++;
if (l == (int)out[i].size()) continue;
if (out[i][l].first == in[i][j].first) {
int p = l;
while (p + 1 < (int)out[i].size() && out[i][p + 1].first == in[i][j].first) p++;
if (l > 0)
graf[in[i][j].second].push_back(suffixNode(out[i][l - 1].second));
if (p + 1 < (int)out[i].size())
graf[in[i][j].second].push_back(prefixNode(out[i][p + 1].second));
} else {
graf[in[i][j].second].push_back(prefixNode(out[i][0].second));
}
}
}
}
// Główna funkcja rozwiązująca pojedynczy test
void solve() {
vector<vector<pair<int,int>>> in(MIL + 1), out(MIL + 1);
int n, m;
cin >> n >> m;
for (int i = 0; i < m; ++i) {
int a, b, c; cin >> a >> b >> c;
out[a].emplace_back(c, i);
in[b].emplace_back(c, i);
}
for (int i = 1; i <= n; ++i) {
sort(in[i].begin(), in[i].end());
sort(out[i].begin(), out[i].end());
}
int maxNode = max({m - 1, prefixNode(n), suffixNode(n)});
vector<vector<int>> graf(maxNode + 1);
buildGraph(n, m, in, out, graf);
CycleDetector cd(graf);
cout << (cd.hasCycle() ? "Cycle detected\n" : "No cycle\n");
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t; cin >> t;
while (t--) solve();
return 0;
}