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<vector<int>> g;
vector<bool> visited;
void dfs(int node, int parent) {
  if (parent != -1) cout << node << " " << parent << "\n";
  for (auto x : g[node]) {
    if (x != parent) dfs(x, node);
  }
}
void solve() {
  int n;
  cin >> n;
  g.clear();
  visited.clear();
  g.resize(n + 1);
  visited.resize(n + 1);
  vector<int> a(n + 1);
  int turns = n / 2;
  turns++;
  queue<int> q;
  int cnt = 0;
  while (turns--) {
    if (cnt >= n - 1) break;
    int node = -1;
    while (!q.empty() && visited[q.front()]) q.pop();
    if (q.empty()) {
      for (int i = 1; i <= n; i++) {
        if (!visited[i]) {
          node = i;
          break;
        }
      }
    } else {
      node = q.front();
      q.pop();
    }
    visited[node] = true;
    cout << "? " << node << "\n";
    cout.flush();
    for (int i = 0; i < n; i++) {
      cin >> a[i];
      if (a[i] == 1 && !visited[i + 1]) {
        g[node].push_back(i + 1);
        g[i + 1].push_back(node);
        cnt++;
        q.push(i + 1);
      }
    }
  }
  cout << "!\n";
  dfs(1, -1);
  cout.flush();
}
int main() {
  int T;
  T = 1;
  for (int i = 0; i < T; i++) solve();
  return 0;
}
