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;
int main() {
  ios_base::sync_with_stdio(0);
  long long n;
  cin >> n;
  long long left = n;
  vector<bool> odw(n + 5);
  vector<int> arr(n + 5);
  vector<vector<int>> G(n + 5, vector<int>());
  map<pair<int, int>, bool> edge;
  vector<pair<int, pair<map<int, bool>, map<int, bool>>>> q;
  q.push_back({1, {{}, {}}});
  for (int i = 0; i < q.size() && left > 0; i++) {
    int v = q[i].first, x;
    if (!odw[v]) {
      left--;
      odw[v] = true;
    }
    if (left == 0) break;
    cout << "? " << v << "\n";
    cout.flush();
    map<int, bool> m, ones;
    int findit = -1;
    for (int j = 1; j <= n; j++) {
      cin >> arr[j];
      if (arr[j] == 2) m[j] = true;
      if (arr[j] == 1) {
        ones[j] = true;
        if (q[i].second.first[j]) findit = j;
      }
    }
    for (int j = 1; j <= n; j++) {
      x = arr[j];
      if (x == 1 && !edge[make_pair(v, j)]) {
        G[v].push_back(j);
        G[j].push_back(v);
        edge[make_pair(v, j)] = true;
        edge[make_pair(j, v)] = true;
        odw[j] = true;
        left--;
      } else if (x == 2 && !odw[j]) {
        if (q[i].second.second[j]) {
          G[findit].push_back(j);
          G[j].push_back(findit);
          edge[make_pair(findit, j)] = true;
          edge[make_pair(j, findit)] = true;
          odw[j] = true;
          left--;
        } else
          q.push_back({j, {ones, m}});
      }
    }
  }
  cout << "!\n";
  for (int i = 1; i <= n; i++) {
    for (int v : G[i]) {
      if (i < v) cout << i << " " << v << "\n";
    }
  }
  cout.flush();
  return 0;
}
