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;
inline bool feq(double a, double b) { return fabs(a - b) < 1e-6; }
void init() {}
int n;
void ask(int q, int *resarr) {
  printf("? %d\n", q);
  fflush(stdout);
  for (int i = 1; i <= n; i++) {
    scanf("%d", resarr + i);
  }
}
vector<int> edges[2005];
int res[2005];
int vis[2005];
bool edgvis[2005][2005];
void solve() {
  scanf("%d", &n);
  queue<int> todo;
  todo.push(1);
  bool flag = true;
  while (!todo.empty()) {
    int t = todo.front();
    todo.pop();
    if (vis[t]) continue;
    vis[t] = true;
    ask(t, res);
    for (int i = 1; i <= n; i++) {
      if (flag && (res[i] % 2 == 0)) {
        todo.push(i);
      }
      if (res[i] == 1) {
        edges[t].push_back(i);
      }
    }
    flag = false;
  }
  printf("!\n");
  for (int i = 1; i <= n; i++) {
    for (auto it = edges[i].begin(); it != edges[i].end(); it++) {
      if (edgvis[i][*it] || edgvis[*it][i]) continue;
      edgvis[i][*it] = true;
      printf("%d %d\n", i, *it);
    }
  }
}
int main(void) {
  init();
  int T = 1;
  for (int t = 1; t <= T; t++) {
    solve();
  }
  return 0;
}
