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 <iostream>
#include <bits/stdc++.h>

#define f(i,a,b) for(int i=a; i<=b; i++)
#define fio ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL)
#define fr(i,a,b) for(int i=a; i>=b; i--)
#define fs(i,n) for(int i=0; i<n; i++)
#define inf (long long)1<<31
#define ll long long
#define ld long double
#define mod 1000000007
#define mp make_pair
#define pb push_back
#define pii pair<int, int>
#define sa(arr) sort(arr.begin(), arr.end())
#define si set<int>
#define sd(arr) sort(arr.begin(), arr.end(), greater<>())

using namespace std;
template <typename t> void Unique(vector<t> &v) { sort(v.begin(), v.end()); v.resize(unique(v.begin(), v.end()) - v.begin()); }
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vlli;

vi dist;
vector<pii> ans;

int gcd(int a, int b) {
	if(b==0)
		return a;
	return gcd(b, a%b);
} 

void query(int r){
	cout << "? " << r << "\n";
	cout.flush();
	f(i,1,dist.size()-1)
		cin >> dist[i];
}

void find_edges(vi q_list){
	fs(i,q_list.size()){
		query(q_list[i]);
		f(j,1,dist.size()){
			if(dist[j]==1){
				int a = q_list[i], b=j;
				if(a>b)
					swap(a,b);
				ans.pb(mp(a,b));
			}
		}
	}
}

void solve(int n){
	dist.resize(n+1);
	query(1);
	vi even, odd;
	f(i,1,n){
		if(dist[i]%2==0 && dist[i]>0)
			even.pb(i);
		else if(dist[i]%2!=0 && dist[i]>0)
			odd.pb(i);
		if(dist[i]==1)
			ans.pb(mp(1,i));
	}
	if(odd.size()>even.size())
		find_edges(even);
	else
		find_edges(odd);
	Unique(ans);
	cout << "!\n";
	fs(i,ans.size()){
		cout << ans[i].first << " " << ans[i].second << endl;
	}
}

int main() {
	fio;
	int n;
	cin >> n;
	solve(n);
	return 0;
}
