#include using namespace std; void build(int root, vector S, const vector& dist, vector>& edges, int n) { if (S.empty()) return; sort(S.begin(), S.end(), [&](int x, int y) { return dist[x] < dist[y]; }); vector direct_children; vector> subs; for (int v : S) { bool found = false; for (size_t j = 0; j < direct_children.size(); ++j) { int c = direct_children[j]; cout << "? " << c << " " << v << endl; cout.flush(); long long dd; cin >> dd; long long expected = dist[v] - dist[c]; if (dd == expected) { subs[j].push_back(v); found = true; break; } } if (!found) { direct_children.push_back(v); subs.emplace_back(); long long w = dist[v] - dist[root]; edges.emplace_back(root, v, w); } } for (size_t j = 0; j < direct_children.size(); ++j) { int c = direct_children[j]; vector sub = subs[j]; if (!sub.empty()) { build(c, sub, dist, edges, n); } } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; cin >> T; for (int t = 0; t < T; ++t) { int n; cin >> n; if (n == 1) { cout << "!" << endl; cout.flush(); continue; } vector dist(n + 1, 0LL); for (int j = 2; j <= n; ++j) { cout << "? 1 " << j << endl; cout.flush(); cin >> dist[j]; } vector all_nodes(n - 1); iota(all_nodes.begin(), all_nodes.end(), 2); sort(all_nodes.begin(), all_nodes.end(), [&](int x, int y) { return dist[x] < dist[y]; }); vector> edges; build(1, all_nodes, dist, edges, n); cout << "!"; for (auto [u, v, w] : edges) { cout << " " << u << " " << v << " " << w; } cout << endl; cout.flush(); } return 0; }