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;
int main() {
  int n;
  cin >> n;
  int edges[n][n];
  cout << "? 1";
  cout << endl;
  cout.flush();
  int oddcount = 0;
  int evencount = 0;
  vector<int> odd;
  vector<int> even;
  for (int i = 0; i < n; i++) {
    int x;
    cin >> x;
    if (x % 2 == 0) {
      evencount++;
      if (i != 0) even.push_back(i + 1);
    } else {
      oddcount++;
      odd.push_back(i + 1);
    }
    if (x == 1) {
      edges[0][i] = 1;
      edges[i][0] = 1;
    }
  }
  vector<int> query;
  if (evencount <= oddcount)
    query = even;
  else
    query = odd;
  for (int i = 0; i < query.size(); i++) {
    int val = query[i];
    string q = "? ";
    q += to_string(query[i]);
    cout << q;
    cout << endl;
    cout.flush();
    for (int j = 0; j < n; j++) {
      int x;
      cin >> x;
      if (x == 1) {
        edges[val - 1][j] = 1;
        edges[j][val - 1] = 1;
      }
    }
  }
  cout << "!" << endl;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < i; j++) {
      if (edges[i][j] == 1) cout << i + 1 << " " << j + 1 << endl;
    }
  }
}
