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;
const long long dx[] = {-1, -1, -1, 0, 1, 1, 1, 0};
const long long dy[] = {-1, 0, 1, 1, 1, 0, -1, -1};
void ask(vector<long long>& vec, long long node) {
  cout << "? " << node << endl;
  for (long long i = 0; i < vec.size(); i++) cin >> vec[i];
  return;
}
signed main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  ;
  long long test = 1;
  while (test--) {
    long long n;
    cin >> n;
    vector<long long> vec(n);
    ask(vec, 1);
    set<long long> done;
    set<pair<long long, long long>> ans;
    vector<vector<long long>> lvl(n + 2, vector<long long>());
    for (long long i = 0; i < vec.size(); i++) {
      lvl[vec[i]].push_back(i + 1);
    }
    for (long long i = 0; i < lvl[1].size(); i++) {
      ans.insert({1, lvl[1][i]});
    }
    done.insert(1);
    for (long long i = 1; i <= n; i++) {
      if (!lvl[i + 1].size()) break;
      set<long long> nxt;
      for (long long j = 0; j < lvl[i].size() - 1; j++) {
        ask(vec, lvl[i][j]);
        for (long long k = 0; k < n; k++) {
          if (vec[k] == 1 and !done.count(k + 1)) {
            nxt.insert(k + 1);
            ans.insert({lvl[i][j], k + 1});
          }
        }
        done.insert(lvl[i][j]);
      }
      long long last = lvl[i][lvl[i].size() - 1];
      for (long long k = 0; k < lvl[i + 1].size(); k++) {
        if (!nxt.count(lvl[i + 1][k])) {
          ans.insert({last, lvl[i + 1][k]});
        }
      }
      done.insert(last);
    }
    cout << "!" << endl;
    for (auto x : ans) {
      cout << x.first << " " << x.second << endl;
    }
  }
  return 0;
}
