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

import java.util.*;
import java.io.*;
 
public class Main2 {
	static class FastReader{ BufferedReader br;StringTokenizer st;public FastReader(){br = new BufferedReader(new InputStreamReader(System.in));}String next(){while (st == null || !st.hasMoreElements()){try{st = new StringTokenizer(br.readLine());}catch (IOException  e){e.printStackTrace();}}return st.nextToken();}int nextInt(){ return Integer.parseInt(next());}long nextLong(){return Long.parseLong(next());}double nextDouble(){return Double.parseDouble(next());}String nextLine(){String str = ""; try{str = br.readLine(); } catch (IOException e) {e.printStackTrace();} return str; }}
	static long mod = (long)(1e9+7);
//	static long mod = 998244353;
//	static Scanner sc = new Scanner(System.in);
	static FastReader sc = new FastReader();
	static PrintWriter out = new PrintWriter(System.out);
	static int n;
	public static void main (String[] args) {
		int t = 1;
//    	t = sc.nextInt();
	    z : for(int tc=1;tc<=t;tc++) {
	    	n = sc.nextInt();
	    	int max = 0;
	    	int a[] = query(0);
	    	List<Integer> tre[] = new ArrayList[n+1];
	    	for(int i=0;i<=n;i++) tre[i] = new ArrayList<>();
	    	int osum = 0, esum = 0;
	    	for(int i=0;i<n;i++) {
	    		if((a[i] & 1) == 1) osum++;
	    		else esum++;
	    	}
	    	if(osum>=esum) {
	    		for(int i=0;i<n;i++) {
	    			if(a[i] == 1) {
	    				tre[0].add(i);
	    				tre[i].add(0);
	    			}
	    		}
	    		for(int i=2;i<n;i+=2) {
	    			for(int j=0;j<n;j++) {
	    				if(a[j] == i) {
	    					int res[] = query(j);
	    					for(int k=0;k<n;k++) {
	    						if(res[k] == 1) {
	    							tre[j].add(k);
	    							tre[k].add(j);
	    						}
	    					}
	    				}
	    			}
	    		}
	    	}
	    	else {
	    		for(int i=1;i<n;i+=2) {
	    			for(int j=0;j<n;j++) {
	    				if(a[j] == i) {
	    					int res[] = query(j);
	    					for(int k=0;k<n;k++) {
	    						if(res[k] == 1) {
	    							tre[j].add(k);
	    							tre[k].add(j);
	    						}
	    					}
	    				}
	    			}
	    		}
	    	}
	    	System.out.println("!");
	    	dfs(tre,0,-1);
			System.out.flush();
	    }
		out.close();
	}
	private static void dfs(List<Integer>[] tre, int u, int par) {
		for(int adj : tre[u]) {
			if(adj == par) continue;
			System.out.println((u+1)+" "+(adj+1));
			System.out.flush();
			dfs(tre,adj,u);
		}
	}
	private static int[] query(int i) {
		System.out.println("? "+(i+1));
		int ret[] = new int[n+1];
		for(int j=0;j<n;j++) ret[j] = sc.nextInt();
		System.out.flush();
		return ret;
	}
	static long gcd(long a,long b) { if(b==0) return a; return gcd(b,a%b); }
	private static void sort(int[] a) {List<Integer> k = new ArrayList<>();for(int val : a) k.add(val);Collections.sort(k);for(int i=0;i<a.length;i++) a[i] = k.get(i);}
	private static void ini(List<Integer>[] tre2){for(int i=0;i<tre2.length;i++){tre2[i] = new ArrayList<>();}}
	private static void init(List<int[]>[] tre2){for(int i=0;i<tre2.length;i++){tre2[i] = new ArrayList<>();}}
	private static void sort(long[] a) {List<Long> k = new ArrayList<>();for(long val : a) k.add(val);Collections.sort(k);for(int i=0;i<a.length;i++) a[i] = k.get(i);}
}