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>
#pragma GCC optimize("Ofast")
using namespace std;
const long MOD = 1e9 + 7;
long n;
vector<long> distance(long v) {
  vector<long> ans(n + 1, 0);
  cout << "? " << v << endl;
  for (long i = 1; i <= n; i++) cin >> ans[i];
  return ans;
}
int main() {
  cin >> n;
  auto dist = distance(1);
  set<pair<long, long> > s;
  for (long i = 1; i <= n; i++) {
    s.insert({-dist[i], i});
  }
  set<pair<long, long> > ans;
  while (-(*s.begin()).first > 1) {
    auto [d, v] = *s.begin();
    s.erase(s.begin());
    auto kek = distance(v);
    vector<pair<long, long> > parent;
    for (long i = 1; i <= n; i++) {
      if (dist[i] + kek[i] == dist[v]) parent.push_back({kek[i], i});
    }
    sort((parent).begin(), (parent).end());
    long last = v;
    for (auto [ds, p] : parent)
      ans.insert({last, p}), last = p, s.erase({-dist[p], p});
  }
  cout << "! " << endl;
  for (auto [e1, e2] : ans)
    if (e1 != e2) cout << e1 << ' ' << e2 << endl;
}
