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;
int32_t main() {
  ios_base::sync_with_stdio(false);
  long long n;
  cin >> n;
  queue<long long> q;
  vector<set<long long>> pr(n);
  vector<long long> used(n);
  long long cnt = 0;
  q.push(0);
  while (q.size()) {
    long long top = q.front();
    q.pop();
    if (used[top]) continue;
    used[top] = 1;
    cout << "? " << top + 1 << endl;
    vector<long long> temp(n);
    for (long long i = 0; i < n; ++i) cin >> temp[i];
    long long one = 0;
    long long two = 0;
    long long rest = 0;
    for (long long i = 0; i < n; ++i) {
      if (temp[i] == 1) one++;
      if (temp[i] == 2) two++;
      if (temp[i] >= 3) rest++;
    }
    long long used_ones = 0;
    for (long long i = 0; i < n; ++i)
      if (temp[i] == 1 && used[i] == 1) used_ones++;
    if (two <= one) {
      for (long long i = 0; i < n; ++i) {
        if (temp[i] == 1) {
          pr[i].insert(top);
        }
        if (!used[i] && temp[i] == 2) {
          if (used_ones != one || rest > 0) q.push(i);
        }
      }
    } else {
      for (long long i = 0; i < n; ++i) {
        if (temp[i] == 1) {
          pr[i].insert(top);
          q.push(i);
        }
      }
    }
  }
  cout << "!" << endl;
  for (long long i = 0; i < n; i++) {
    for (auto x : pr[i]) {
      if (x == i) continue;
      pr[x].erase(i);
      cout << i + 1 << " " << x + 1 << endl;
    }
  }
  return 0;
}
