#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9;
vector<vector<pair<int, int>>> adj;
vector<int> energy;
vector<bool> visited;
bool impossible;
void dfs(int node) {
visited[node] = true;
for (auto &edge : adj[node]) {
int next_node = edge.first;
int weight = edge.second;
if (energy[next_node] == INF) {
energy[next_node] = energy[node] + weight;
dfs(next_node);
} else if (energy[next_node] != energy[node] + weight) {
impossible = true;
}
}
}
int solve(int n, int m) {
adj.clear();
energy.assign(n + 1, INF);
visited.assign(n + 1, false);
adj.resize(n + 1);
impossible = false;
for (int i = 0; i < m; ++i) {
int u, v, b;
cin >> u >> v >> b;
if (b == 1) {
adj[u].emplace_back(v, 1);
adj[v].emplace_back(u, -1);
} else {
adj[u].emplace_back(v, 1);
adj[v].emplace_back(u, 1);
}
}
for (int i = 1; i <= n; ++i) {
if (!visited[i]) {
energy[i] = 0;
dfs(i);
}
}
if (impossible) {
return -1;
}
int min_energy = INF, max_energy = -INF;
for (int i = 1; i <= n; ++i) {
if (energy[i] != INF) {
min_energy = min(min_energy, energy[i]);
max_energy = max(max_energy, energy[i]);
}
}
return max_energy - min_energy;
}
int main() {
int t;
cin >> t;
while (t--) {
int n, m;
cin >> n >> m;
int result = solve(n, m);
if (result == -1) {
cout << "Impossible to form a stellar gradient with the given configuration." << endl;
} else {
cout << "Maximum stellar gradient: " << result << endl;
}
}
return 0;
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7Cgpjb25zdCBpbnQgSU5GID0gMWU5Owp2ZWN0b3I8dmVjdG9yPHBhaXI8aW50LCBpbnQ+Pj4gYWRqOwp2ZWN0b3I8aW50PiBlbmVyZ3k7CnZlY3Rvcjxib29sPiB2aXNpdGVkOwpib29sIGltcG9zc2libGU7Cgp2b2lkIGRmcyhpbnQgbm9kZSkgewogICAgdmlzaXRlZFtub2RlXSA9IHRydWU7CiAgICBmb3IgKGF1dG8gJmVkZ2UgOiBhZGpbbm9kZV0pIHsKICAgICAgICBpbnQgbmV4dF9ub2RlID0gZWRnZS5maXJzdDsKICAgICAgICBpbnQgd2VpZ2h0ID0gZWRnZS5zZWNvbmQ7CiAgICAgICAgaWYgKGVuZXJneVtuZXh0X25vZGVdID09IElORikgewogICAgICAgICAgICBlbmVyZ3lbbmV4dF9ub2RlXSA9IGVuZXJneVtub2RlXSArIHdlaWdodDsKICAgICAgICAgICAgZGZzKG5leHRfbm9kZSk7CiAgICAgICAgfSBlbHNlIGlmIChlbmVyZ3lbbmV4dF9ub2RlXSAhPSBlbmVyZ3lbbm9kZV0gKyB3ZWlnaHQpIHsKICAgICAgICAgICAgaW1wb3NzaWJsZSA9IHRydWU7CiAgICAgICAgfQogICAgfQp9CgppbnQgc29sdmUoaW50IG4sIGludCBtKSB7CiAgICBhZGouY2xlYXIoKTsKICAgIGVuZXJneS5hc3NpZ24obiArIDEsIElORik7CiAgICB2aXNpdGVkLmFzc2lnbihuICsgMSwgZmFsc2UpOwogICAgYWRqLnJlc2l6ZShuICsgMSk7CiAgICBpbXBvc3NpYmxlID0gZmFsc2U7CgogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBtOyArK2kpIHsKICAgICAgICBpbnQgdSwgdiwgYjsKICAgICAgICBjaW4gPj4gdSA+PiB2ID4+IGI7CiAgICAgICAgaWYgKGIgPT0gMSkgewogICAgICAgICAgICBhZGpbdV0uZW1wbGFjZV9iYWNrKHYsIDEpOwogICAgICAgICAgICBhZGpbdl0uZW1wbGFjZV9iYWNrKHUsIC0xKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBhZGpbdV0uZW1wbGFjZV9iYWNrKHYsIDEpOwogICAgICAgICAgICBhZGpbdl0uZW1wbGFjZV9iYWNrKHUsIDEpOwogICAgICAgIH0KICAgIH0KCiAgICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKICAgICAgICBpZiAoIXZpc2l0ZWRbaV0pIHsKICAgICAgICAgICAgZW5lcmd5W2ldID0gMDsKICAgICAgICAgICAgZGZzKGkpOwogICAgICAgIH0KICAgIH0KCiAgICBpZiAoaW1wb3NzaWJsZSkgewogICAgICAgIHJldHVybiAtMTsKICAgIH0KCiAgICBpbnQgbWluX2VuZXJneSA9IElORiwgbWF4X2VuZXJneSA9IC1JTkY7CiAgICBmb3IgKGludCBpID0gMTsgaSA8PSBuOyArK2kpIHsKICAgICAgICBpZiAoZW5lcmd5W2ldICE9IElORikgewogICAgICAgICAgICBtaW5fZW5lcmd5ID0gbWluKG1pbl9lbmVyZ3ksIGVuZXJneVtpXSk7CiAgICAgICAgICAgIG1heF9lbmVyZ3kgPSBtYXgobWF4X2VuZXJneSwgZW5lcmd5W2ldKTsKICAgICAgICB9CiAgICB9CgogICAgcmV0dXJuIG1heF9lbmVyZ3kgLSBtaW5fZW5lcmd5Owp9CgppbnQgbWFpbigpIHsKICAgIGludCB0OwogICAgY2luID4+IHQ7CiAgICB3aGlsZSAodC0tKSB7CiAgICAgICAgaW50IG4sIG07CiAgICAgICAgY2luID4+IG4gPj4gbTsKICAgICAgICBpbnQgcmVzdWx0ID0gc29sdmUobiwgbSk7CiAgICAgICAgaWYgKHJlc3VsdCA9PSAtMSkgewogICAgICAgICAgICBjb3V0IDw8ICJJbXBvc3NpYmxlIHRvIGZvcm0gYSBzdGVsbGFyIGdyYWRpZW50IHdpdGggdGhlIGdpdmVuIGNvbmZpZ3VyYXRpb24uIiA8PCBlbmRsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNvdXQgPDwgIk1heGltdW0gc3RlbGxhciBncmFkaWVudDogIiA8PCByZXN1bHQgPDwgZW5kbDsKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gMDsKfQo=