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;
vector<pair<int, int>> ans;
void dfs(int v, vector<vector<int>> &g, vector<int> &m) {
  m[v] = 1;
  for (auto adj : g[v]) {
    if (!m[adj]) {
      ans.push_back({v, adj});
      dfs(adj, g, m);
    }
  }
}
int main() {
  int n;
  scanf(" %d", &n);
  int q = n / 2 + (n & 1);
  vector<vector<int>> g(n + 1);
  vector<int> marked(n + 1, 0);
  queue<int> ask;
  ask.push(1);
  marked[1] = 1;
  while (q--) {
    if (!ask.size()) break;
    int next = ask.front();
    ask.pop();
    printf("? %d\n", next);
    fflush(stdout);
    int nums[n + 1];
    for (int i = 1; i <= n; ++i) scanf(" %d", &nums[i]);
    int who = -1;
    vector<int> dist2, dist1;
    for (int i = 1; i <= n; ++i) {
      if (nums[i] == 1) {
        g[next].push_back(i);
        g[i].push_back(next);
        if (!marked[i]) {
          dist1.push_back(i);
          marked[i] = 1;
        }
      }
      if (!marked[i] && nums[i] == 2) {
        dist2.push_back(i);
        marked[i] = 1;
      }
    }
    if (dist2.size() + ask.size() <= q) swap(dist1, dist2);
    for (auto va : dist1) ask.push(va);
  }
  fill(marked.begin(), marked.end(), 0);
  dfs(1, g, marked);
  puts("!");
  for (auto va : ans) printf("%d %d\n", va.first, va.second);
  fflush(stdout);
  return 0;
}
