5
5 3
2 4
3 1
4 5
 4
2 4
3 2
2 1
 5
5 3
2 4
3 1
4 5
 2
1 2
 4
3 4
2 3
3 1
 10
8 10
2 9
7 8
4 1
7 3
4 7
2 5
2 4
4 6
 5
3 4
3 2
3 1
1 5
 3
1 2
2 3
 5
1 2
1 3
1 4
1 5

1 2
2 3
2 4
 1 3
2 4
3 5
4 5
 1 2
 1 3
2 3
3 4
 1 4
2 4
2 5
2 9
3 7
4 6
4 7
7 8
8 10
 1 3
1 5
2 3
3 4
 1 2
2 3
 1 2
1 3
1 4
1 5

#include <bits/stdc++.h>
using namespace std;
#pragma warning(disable : 4996)
stringstream err;
void debug() {
  string a;
  while (getline(err, a)) {
    cerr << a << "\n";
  }
}
mt19937 rnd(1231);
const int MAXN = 100000;
const long long int M = 1000000007;
struct pair_hash {
  size_t operator()(const pair<int, int>& v) const {
    return v.first * 31 + v.second;
  }
};
int solve(int case_num) {
  int n;
  cin >> n;
  int k = (n + 1) / 2;
  int root = rnd() % n;
  vector<int> parent(n, -1);
  parent[root] = -2;
  stack<pair<int, int>> toAsk;
  vector<vector<int>> asked;
  toAsk.push({root, -1});
  vector<int> leafs;
  vector<vector<int>> answers(n);
  while (!toAsk.empty() && k > 0) {
    k--;
    int now = toAsk.top().first;
    int p = toAsk.top().second;
    toAsk.pop();
    cout << now + 1 << endl;
    vector<int> answ(n);
    for (auto& elem : answ) cin >> elem;
    ;
    answers[now] = answ;
    asked.push_back(answ);
    int cntOne = 0;
    int nxt = -1;
    for (int i = 0; i < n; i++) {
      if (i == p) continue;
      if (answ[i] == 1) {
        cntOne++;
        nxt = i;
      }
    }
    if (cntOne == 0)
      leafs.push_back(now);
    else if (cntOne == 1) {
      for (int i = 0; i < n; i++) {
        if (i == p) continue;
        if (answ[i] == 1) {
          parent[i] = now;
        }
      }
      for (int i = 0; i < n; i++) {
        if (answ[i] == 2 && parent[i] == -1) {
          parent[i] = nxt;
          toAsk.push({i, nxt});
        }
      }
    } else {
      for (int i = 0; i < n; i++) {
        if (i == p) continue;
        if (answ[i] == 1) {
          parent[i] = now;
          toAsk.push({i, now});
        }
      }
    }
  }
  unordered_set<pair<int, int>, pair_hash> answ;
  for (int i = 0; i < n; i++) {
    if (parent[i] < 0) continue;
    int a = i;
    int b = parent[i];
    answ.insert({min(a, b), max(a, b)});
  }
  int leafsId = 0;
  while (answ.size() < n - 1) {
    if (leafsId >= leafs.size()) break;
    int l = leafs[leafsId];
    int p = parent[l];
    leafsId++;
    vector<int>& answL = answers[l];
    vector<int>& answP = answers[p];
    vector<pair<int, int>> good;
    for (int i = 0; i < n; i++) {
      if (answL[i] == answP[i] + 1) {
        good.push_back({i, answL[i]});
      }
    }
    sort(good.begin(), good.end(), [](pair<int, int>& a, pair<int, int>& b) {
      return a.second < b.second;
    });
    for (int i = 1; i < good.size(); i++) {
      int a = good[i - 1].first;
      int b = good[i].first;
      if (good[i - 1].second == good[i].second) break;
      answ.insert({min(a, b), max(a, b)});
    }
  }
  cout << "!\n";
  for (auto& p : answ) {
    cout << p.first + 1 << " " << p.second + 1 << "\n";
  }
  cout.flush();
  return 0;
}
void stresstest() {
  while (true) {
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  int t = 1;
  for (int i = 1; i <= t; i++) {
    if (solve(i) == -1) break;
  }
}
