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.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class LAT_RoundP4{
    static FS sc = new FS();
    static PrintWriter pw = new PrintWriter(System.out);
    static int n;
    private static int[] query(int doubt) {
        pw.println("? "+doubt);
        pw.flush();
        int[] resp = sc.nextArray(n);
        return resp;
    }
    public static void main(String[] args){
        n = sc.nextInt();
        ArrayList<Integer>[] edges = new ArrayList[n+1];
        for(int i=1; i<=n; i++){
            edges[i] = new ArrayList<>();
        }
        int doubt = 1;
        ArrayList<Integer> diva = new ArrayList<>();
        ArrayList<Integer> divb = new ArrayList<>();
        int[] colors = query(doubt);
        for(int i=0; i<n; i++){
            if(colors[i]%2==0){
                diva.add(i+1);
            }
            else{
                divb.add(i+1);
            }
        }
        ArrayList<Integer> finalist = diva.size()<=divb.size()?diva:divb;
        for(int node : finalist){
            if(node==1){
                for(int i=0; i<n; i++){
                    if(colors[i]==1){
                        edges[node].add(i+1);
                    }
                }
                continue;
            }
            int[] response = query(node);
            for(int i=0; i<n; i++){
                if(response[i]==1){
                    edges[node].add(i+1);
                }
            }
        }
        StringBuilder sb = new StringBuilder();
        for(int i=1; i<=n; i++){
            for(int dest : edges[i]){
                sb.append(i+" "+dest+"\n");
            }
        }
        pw.println("!\n"+sb.substring(0, sb.length()).toString());
        pw.flush();
        pw.close();
    }

    static class FS{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer("");
    
        String next(){
            while(!st.hasMoreElements()){
                try{
                    st = new StringTokenizer(br.readLine());
                } catch(Exception ignored){
                }
            }
            return st.nextToken();
        }
        
        int[] nextArray(int n){
            int[] a = new int[n];
            for(int i = 0; i < n; i++){
                a[i] = nextInt();
            }
            return a;
        }
        
        long[] nextLongArray(int n){
            long[] a = new long[n];
            for(int i = 0; i < n; i++){
                a[i] = nextLong();
            }
            return a;
        }
        
        int nextInt(){
            return Integer.parseInt(next());
        }
        
        long nextLong(){
            return Long.parseLong(next());
        }
        
        double nextDouble(){
            return Double.parseDouble(next());
        }
    }
}