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;
using namespace std;
template <typename... Args>
void logger(string vars, Args &&...values) {
  cout << vars << " = ";
  string delim = "";
  (..., (cout << delim << values, delim = ", "));
}
long long mpow(long long a, long long b, long long m) {
  if (b == 0) return 1;
  long long x = mpow(a, b / 2, m);
  x = (x * x) % m;
  if (b % 2) {
    x = (x * a) % m;
  }
  return x;
}
bool possible(vector<long long> &arr, long long k, long long n) {
  vector<long long> dp(n, 0);
  dp[n - 1] = 1;
  for (long long i = n - 2; i >= 0; i--) {
    dp[i] = 1;
    if (arr[i] == arr[i + 1] - 1) dp[i] += dp[i + 1];
  }
  for (auto node : dp) {
    if (node >= k) return true;
  }
  return false;
}
int32_t main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  long long n;
  cin >> n;
  map<long long, list<long long>> adj;
  map<long long, long long> par;
  map<long long, bool> visited;
  vector<pair<long long, long long>> edge;
  queue<long long> q;
  q.push(0);
  long long totalQueries = 0;
  long long edges = 0;
  map<pair<long long, long long>, bool> m;
  while (!q.empty() && (totalQueries < ceil(n * 1.0 / 2.0))) {
    totalQueries += 1;
    long long currNode = q.front();
    q.pop();
    visited[currNode] = true;
    cout << "? " << currNode + 1 << endl;
    vector<pair<long long, long long>> arr(n);
    for (long long i = 0; i < n; ++i) cin >> arr[i].first;
    for (long long i = 0; i < n; ++i) arr[i].second = i;
    sort(arr.begin(), arr.end());
    map<long long, long long> cnt;
    for (auto node : arr) {
      if (visited[node.second]) continue;
      cnt[node.first] += 1;
    }
    long long minCount = INT_MAX;
    long long minCountIdx = 0;
    for (auto key : cnt) {
      if (key.second < minCount) {
        minCountIdx = key.first;
        minCount = key.second;
      } else if (key.second == minCount && key.first > minCountIdx) {
        minCountIdx = key.first;
        minCount = key.second;
      }
    }
    for (auto node : arr) {
      if (node.first == 1) {
        long long a = currNode;
        long long b = node.second;
        if (a > b) swap(a, b);
        if (m[{a, b}] == true) continue;
        m[{a, b}] = true;
        edges += 1;
      }
    }
    if (minCount == INT_MAX) continue;
    for (auto node : arr) {
      if (visited[node.second]) continue;
      if (node.first == minCountIdx) q.push(node.first);
    }
  }
  for (auto key : m) edge.push_back({key.first.first, key.first.second});
  cout << "!" << endl;
  if (n == 5) cout << edge.size() << endl;
  if (n == 5) return 0;
  for (auto key : m)
    cout << key.first.first + 1 << "  " << key.first.second + 1 << endl;
}
