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"
// DEBUG //
#define dbg(x)        cout <<  "Line " << __LINE__ << ": " << #x << " = " << x << endl;
#define pair_dbg(v)     cout <<  "Line " << __LINE__ << ": " << #v << " = "; cout << "(" << v.first << ", " << v.second << ") " << endl;
#define vec_dbg(v) cout <<  "Line " << __LINE__ << ": " << \
#v << " = "; cout << "["; for(int i = 0; i < v.size(); i++) cout << v[i] << " "; cout << "]"<< endl;
#define matrix_dbg(v) cout <<  "Line " << __LINE__ << ": " << \
#v << " = \n";\
for(int i = 0; i < v.size(); i++) { \
    cout << "[";\
    for (int g = 0; g < v[i].size(); g++) {\
        cout << v[i][g] << " ";\
    }\
    cout << "]\n";\
} cout << endl;
#define vec_pair_dbg(v) cout <<  "Line " << __LINE__ << ": " << #v << " = "; cout << "["; for(auto& i : v) cout << "("<<i.first << ", " << i.second << "), "; cout << "]"<< endl;
#define arr_dbg(a)    cout <<  "Line " << __LINE__ << ": " << #a << " = "; for(int i = 0; i < sizeof(a)/sizeof(a[0]); i++) cout << a[i] << ", "; cout << endl;
#define rvec(arr) for (int i = 0; i < arr.size(); i++) cin >> arr[i];
#define ovec(arr) for (int i = 0; i < arr.size(); i++) cout << arr[i] << " "; cout << endl;
#define pb push_back
#define int long long
#define ld long double
using namespace std;
#define F first
#define S second
#define X second
#define Y first
#define MOD 1000000007
#define gayMOD 998244353
#define big 1000000000000000
#define vi vector<int>
#define pii pair<int,int>
#define matrix vector<vi>
//#define endl "\n";
//int n;
vector<vector<int>>m;
vector<set<int>>graph;
vector<bool>used;
void solve(){
    int n;
    cin >> n;
    vector<int>response(n);
    used = vector<bool>(n,false);
    graph = vector<set<int>>(n,set<int>());
    cout << "?" << " " << 1 << endl;
    rvec(response);
    int odd = 0;
    for (int i = 0; i < n; i++){
        odd+=response[i]%2;
    }
    if (odd < (n+1)/2){
        // Не в той доле
        for (int i = 0; i < n; i++){
            if (response[i]%2 == 0){
                used[i] = true;
            }
        }
    } else {
        used[0] = true;
        for (int i = 0; i < n; i++){
            if (response[i]%2 == 1){
                used[i] = true;
            }
            if (response[i] == 1){
                used[i] = true;
                graph[0].insert(i);
            }
        }
    }
    for (int i = 0; i < n; i++){
        if (!used[i]){
            used[i] = true;
            cout << "?" << " " << i+1 << endl;
            rvec(response);
            for (int g = 0; g < n; g++){
                if (response[g] == 1){
                    if (graph[g].find(i) == graph[g].end()){
                        graph[i].insert(g);
                    }
                    used[g] = true;
                }
            }
        }
    }
    cout << "!" << endl;
    for (int i = 0; i < n; i++){
        for (auto v: graph[i]){
            cout << i+1 << " " << v + 1 << endl;
        }
    }


}
signed main() {
    //freopen("/Users/artembreznev/CLionProjects/cp/input.txt", "r", stdin);
    //freopen("/Users/artembreznev/CLionProjects/cp/output.txt", "w", stdout);
    cin.tie(NULL);
    ios_base::sync_with_stdio(false);
    solve();
    return 0;
}


