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

///////////////////////////////    _LeMur_
#define _CRT_SECURE_NO_WARNINGS
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cassert>
#include <chrono>
#include <random>
#include <bitset>
#include <cstdio>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <ctime>
#include <cmath>
#include <list>
#include <map>
#include <set>

using namespace std;

const int N = 2005;
const int inf = 1000 * 1000 * 1000;
const int mod = 1000 * 1000 * 1000 + 7;
mt19937 myrand(chrono::steady_clock::now().time_since_epoch().count());

int n;

int d[N][N];

set < pair<int, int> > edges;

void query(int v) {
  cout << "? " << v << endl;
  cout.flush();
  for (int i = 1; i <= n; i++) {
    scanf("%d", &d[v][i]);
    if (d[v][i] == 1) {
      int a = v, b = i;
      if (a > b) swap(a, b);
      edges.insert(make_pair(a, b));
    }
  }
}

int main() {
  cin >> n;

  query(1);

  int cnt0 = -1, cnt1 = 0;
  for (int i = 1; i <= n; i++) {
    if (d[1][i] % 2 == 0) {
      ++cnt0;
    } else {
      ++cnt1;
    }
  }

  if (cnt0 <= cnt1) {
    for (int i = 2; i <= n; i++) {
      if (d[1][i] % 2 == 0) {
        query(i);
      }
    }
  } else {
    for (int i = 2; i <= n; i++) {
      if (d[1][i] % 2) {
        query(i);
      }
    }
  }

  cout << "!" << endl;
  cout.flush();
  for (auto x: edges) {
    cout << x.first << " " << x.second << endl;
    cout.flush();
  }
  return 0;
}
