#define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #define Assert assert //#define Assert(x) enum { MaxQueries = 20, MaxN = 100000 }; struct TestDriver { int n; vector> neighLists; int nQueries = 0; void Init(int n_, mt19937_64 &rnd) { n = n_; neighLists.clear(); neighLists.resize(n); Assert(n >= 2); Assert(n <= MaxN); nQueries = 0; vector order(n); for (int u = 0; u < n; ++u) order[u] = u; shuffle(order.begin(), order.end(), rnd); for (int i = 1; i < n; ++i) { int u = order[i], v = order[uniform_int_distribution(0, i - 1)(rnd)]; if (false) v = order[i - 1]; // to make the 'tree' a single long chain neighLists[u].emplace_back(v); neighLists[v].emplace_back(u); } } int GetN() const { return n; } void Query(const vector &query, vector &answer) { Assert(query.size() == n); answer.resize(n); for (int qi : query) Assert(qi == 0 || qi == 1); Assert(nQueries < MaxQueries); for (int u = 0; u < n; ++u) { int a = 0; for (int v : neighLists[u]) a += query[v]; answer[u] = a; } } bool Answer(const vector> edges) const { vector> neighLists2(n); for (auto [u, v] : edges) { Assert(0 <= u); Assert(u < n); Assert(0 <= v); Assert(v < n); Assert(u != v); neighLists2[u].emplace_back(v); neighLists2[v].emplace_back(u); } vector L1; for (int u = 0; u < n; ++u) { L1 = neighLists[u]; sort(L1.begin(), L1.end()); auto &L2 = neighLists2[u]; sort(L2.begin(), L2.end()); bool ok = (L1 == L2); Assert(ok); if (! ok) return false; } return true; } }; struct ServerInterface { int GetN() const { int n; int ok_ = scanf("%d", &n); Assert(ok_ == 1); Assert(2 <= n); Assert(n <= MaxN); return n; } void Query(const vector &query, vector &answer) const { int n = query.size(); string s(n, '?'); answer.resize(n); for (int u = 0; u < n; ++u) s[u] = '0' + query[u]; printf("QUERY %s\n", s.c_str()); fflush(stdout); int ok_; for (int u = 0; u < n; ++u) { ok_ = scanf("%d", &answer[u]); Assert(ok_ == 1); } } bool Answer(const vector> edges) const { printf("ANSWER\n"); for (auto [u, v] : edges) printf("%d %d\n", u + 1, v + 1); fflush(stdout); return true; } }; template void Solve(Interface &&interface) { int n = interface.GetN(); // Use a query with all 1's to get the degrees of the nodes. vector query(n, 1), degrees; interface.Query(query, degrees); // queryAnswers[b][u] = the number of u's neighbours whose number has bit b set int nBits = 1; while ((1 << nBits) < n) ++nBits; vector> queryAnswers(nBits); for (int b = 0; b < nBits; ++b) { for (int u = 0; u < n; ++u) query[u] = (u >> b) & 1; interface.Query(query, queryAnswers[b]); } // If a node 'u' has degree 1, it has only one neighbour. We can // reconstruct the number of this neighbour bit by bit from queryAnswers[b][u]. // Let 'v' be this neighbour. We will then delete 'u' from the tree, // which means that queryAnswers[b][v] needs to be decreased by for // those bits 'b' which are set in 'u'. vector parent(n, -1); stack toDo; for (int u = 0; u < n; ++u) { Assert(degrees[u] > 0); Assert(degrees[u] < n); if (degrees[u] == 1) toDo.push(u); } int root = -1; while (! toDo.empty()) { // Let 'u' be the next leaf. int u = toDo.top(); toDo.pop(); Assert(parent[u] < 0); if (degrees[u] == 0) { Assert(root < 0); root = u; continue; } Assert(degrees[u] == 1); // Reconstruct its only neighbour, 'v'. int v = 0; for (int b = 0; b < nBits; ++b) { int a = queryAnswers[b][u]; Assert(a == 0 || a == 1); if (a == 1) v |= (1 << b); } Assert(parent[v] < 0); parent[u] = v; // Delete 'u' from the tree. for (int b = 0; b < nBits; ++b) { int &a = queryAnswers[b][v]; Assert(a >= 0 && a <= degrees[v]); if (u & (1 << b)) { Assert(a >= 1); --a; } } // Perhaps this makes 'v' a leaf as well. --degrees[v]; if (degrees[v] == 1) toDo.push(v); } Assert(root >= 0); Assert(parent[root] < 0); // Report the results. vector> edges; edges.reserve(n - 1); for (int u = 0; u < n; ++u) if (u != root) { Assert(parent[u] >= 0); Assert(parent[u] != u); edges.emplace_back(u, parent[u]); } interface.Answer(edges); } int TestRandom() { for (int nIter = 0; ; ++nIter) { mt19937_64 r(987654 + nIter); int n = uniform_int_distribution(2, MaxN)(r); fprintf(stderr, "%d] n = %d \r", nIter, n); TestDriver td; td.Init(n, r); Solve(td); } return 0; } int main() { if (false) return TestRandom(); Solve(ServerInterface()); return 0; }