#include using namespace std; long long query(int u, int v) { cout << "? " << u << " " << v << endl; cout.flush(); long long d; if (!(cin >> d)) exit(0); return d; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; if (!(cin >> T)) return 0; while (T--) { int n; if (!(cin >> n)) return 0; if (n <= 1) { cout << "! " << endl; cout.flush(); continue; } const long long INF = (1LL<<62); vector best(n+1, INF); vector from(n+1, -1); vector in(n+1, 0); vector> edges; int start = 1; in[start] = 1; for (int v = 1; v <= n; ++v) { if (v == start) continue; long long d = query(start, v); best[v] = d; from[v] = start; } for (int iter = 1; iter <= n - 1; ++iter) { int w = -1; long long md = INF; for (int v = 1; v <= n; ++v) { if (!in[v] && best[v] < md) { md = best[v]; w = v; } } if (w == -1) break; in[w] = 1; edges.emplace_back(from[w], w, best[w]); for (int v = 1; v <= n; ++v) { if (!in[v]) { long long d = query(w, v); if (d < best[v]) { best[v] = d; from[v] = w; } } } } cout << "! "; for (auto &e : edges) { int u, v; long long w; tie(u, v, w) = e; cout << u << " " << v << " " << w << " "; } cout << endl; cout.flush(); } return 0; }