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.*;
/**
 *
 * @author alanl
 */
public class Solve {

    /**
     * @param args the command line arguments
     */
    static BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
    static StringTokenizer st;
    static PrintWriter pr = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
    public static void main(String[] args) throws IOException {
        int n = readInt();
        if(n==2){
            println("!");
            println("1 2");
            return;
        }
        Set<String>s = new HashSet();
        Queue<Integer>Q = new LinkedList();
        Set<Integer>s1 = new HashSet(), s2 = new HashSet();
        println("? 1");
        int[]dis = new int[n];
        for(int i = 1; i<=n; i++){
            dis[i-1] = readInt();
            if(i==1)continue;
            if(dis[i-1]%2==0){
                s1.add(i); //odd
            }
            else s2.add(i);
            if(dis[i-1]==1){
                String a = 1+" "+(i), b = (i)+" "+1;
                if(!s.contains(a) && !s.contains(b)){
                    s.add(a);
                }
            }
        }
        if(s1.size()>s2.size()){
            for(int i:s2)Q.add(i);
        }
        else{
            for(int i:s1)Q.add(i);
        }
        int cnt = 0;
        boolean[]vis = new boolean[n+1];
        while(!Q.isEmpty()){
            int cur = Q.poll();
            vis[cur] = true;
            println("? "+cur);
            System.out.flush();
            int[]arr = new int[n];
            for(int i = 0; i<n; i++){
                arr[i] = readInt();
                if(arr[i]==1){
                    String a = cur+" "+(i+1), b = (i+1)+" "+cur;
                    if(!s.contains(a) && !s.contains(b)){
                        s.add(a);
                    }
                }
            }
            cnt++;
            if(cnt==(int)(Math.ceil(n/1.0/2))-1)break;
        }
        println("!");
        for(String i:s){
            println(i);
        }
    }
    static String next () throws IOException {
        while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(input.readLine().trim());
        return st.nextToken();
    }
    static long readLong () throws IOException {
        return Long.parseLong(next());
    }
    static int readInt () throws IOException {
        return Integer.parseInt(next());
    }
    static double readDouble () throws IOException {
        return Double.parseDouble(next());
    }
    static char readChar () throws IOException {
        return next().charAt(0);
    }
    static String readLine () throws IOException {
        return input.readLine().trim();
    }
    static void print(Object b) {
        System.out.print(b);
    }
    static void println(Object b) {
        System.out.println(b);
    }
    static void println() {
        System.out.println();
    }
}
