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.*;
import java.lang.reflect.Array;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;

public class copy {

    static ArrayList<ArrayList<Integer>> arr;

    public static void makeCombiUtil(ArrayList<Integer> tmp, int n, int left, int k)
    {
        // Pushing this vector to a vector of vector
        if (k == 0) {
            //System.out.println(tmp);
            ArrayList<Integer> copy=new ArrayList<>(tmp);
            arr.add(copy);
            return;
        }

        // i iterates from left to n. First time
        // left will be 1
        for (int i = left; i <= n; ++i)
        {
            tmp.add(i);
            makeCombiUtil(tmp, n, i + 1, k - 1);

            // Popping out last inserted element
            // from the vector
            tmp.remove(tmp.size()-1);
        }
    }

    static void makeCombi(int n, int k,ArrayList<Integer> tmp)
    {


        makeCombiUtil( tmp, n, 1, k);

    }


    public static void diam(int start,int d,ArrayList<ArrayList<Integer>> arr,int[] dist,int parent)
    {
        dist[start]=d;
        for(int i:arr.get(start))
        {
            if(i!=parent)
            {
                diam(i,d+1,arr,dist,start);
            }
        }




    }

    public static long kthElement( int nums1[], int nums2[], int n, int m, int k) {

        int low=0,high=nums1.length;
        int n1=nums1.length,n2=nums2.length;
        while(low<=high)
        {
            System.out.println(low+" "+high);
            int cut1=(low+high)/2;
            int cut2=k-cut1;
//            if(cut2>nums2.length)
//            {
//                low=cut1+1;
//                continue;
//
//            }
            System.out.println(cut1+" "+cut2);

            int l1=cut1>0?nums1[cut1-1]:Integer.MIN_VALUE;
            int l2=cut2>0?nums2[cut2-1]:Integer.MIN_VALUE;
            int r1=cut1<n1? nums1[cut1]:Integer.MAX_VALUE;
            int r2=cut2<n2? nums2[cut2]:Integer.MAX_VALUE;

            if(l1<=r2 && l2<=r1)
            {

                return Math.max(l1,l2);
            }

            else if(l1>r2)
            {
                high=cut1-1;
            }
            else
                low=cut1+1;
        }

        return 0;



    }

    public static int checker_high(long[] arr,int i,long l,int N)
    {
        int low=i+1;
        int high=arr.length-1;
        long search=l-arr[i];
        while(low<=high)
        {
            int mid=(low+high)/2;

            if(arr[mid]<=search)
            {
                if(mid+1<N && arr[mid+1]<=search)
                {
                    low=mid+1;
                }
                else
                    return mid;
            }
            else
                high=mid-1;
        }

        return -1;
    }

    public static int checker(long[] arr,int i,long l)
    {
        int low=i+1;
        int high=arr.length-1;
        long search=l-arr[i];
        while(low<=high)
        {
            int mid=(low+high)/2;

            if(arr[mid]>=search)
            {
                if(mid-1>i && arr[mid-1]>=search)
                {
                    high=mid-1;
                }
                else
                    return mid;
            }
            else
                low=mid+1;
        }

        return -1;
    }


    static long  binpow(long  a, long  b, long  m) {
        a %= m;
        long  res = 1;
        while (b > 0) {
            if ((b & 1)==1)
                res = res * a % m;
            a = a * a % m;
            b >>= 1;
        }
        return res;
    }











    public static void main(String[] args)throws IOException
    {
        Reader.init(System.in);
        BufferedWriter output=new BufferedWriter(new OutputStreamWriter(System.out));

        int N=Reader.nextInt();
        int[] arr=new int[N];
        int start=1;
        boolean[] visited=new boolean[N];
        int[][] ans=new int[N-1][2];
        System.out.println("? "+start);
        System.out.flush();
        int c1=0,c2=0;
        int k=0;
        for(int i=0;i<N;i++)
        {
            arr[i]=Reader.nextInt();
            if(arr[i]%2==0 && arr[i]!=0)
                ++c1;
            else
            {
                ++c2;
                if(arr[i]==1)
                {
                    ans[k][0]=start;
                    ans[k++][1]=i+1;
                }
            }

        }

        ArrayList<Integer> edges=new ArrayList<>();

        if(c1<c2)
        {
            for(int i=0;i<N;i++)
            if(arr[i]%2==0 && arr[i]!=0)
                edges.add(i);

        }
        else
        {
            for(int i=0;i<N;i++)
                if(arr[i]%2!=0)
                    edges.add(i);
        }
        visited[0]=true;

        for(int i=0;i<edges.size();i++)
        {
            System.out.println("? "+(edges.get(i)+1));
            System.out.flush();
            for(int j=0;j<N;j++)
            {
                arr[j]=Reader.nextInt();

            }
            visited[edges.get(i)]=true;


            for(int j=0;j<N;j++)
            {
                if(arr[j]==1 && !visited[j])
                {
                    //output.write(i+1+" "+start+"\n");
                    ans[k][0]=j+1;
                    ans[k++][1]=edges.get(i)+1;

                }


            }

        }
        System.out.println("!");
        for(int i=0;i<N-1;i++)
            System.out.println(ans[i][0]+" "+ans[i][1]);
        System.out.flush();











        //output.flush();
    }
}

class Reader {
    static BufferedReader reader;
    static StringTokenizer tokenizer;

    static void init(InputStream input) {
        reader = new BufferedReader(
                new InputStreamReader(input));
        tokenizer = new StringTokenizer("");
    }

    static String next() throws IOException {
        while (!tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(
                    reader.readLine());
        }
        return tokenizer.nextToken();
    }

    static int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    static long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    static double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }
}
class point
{
    int leaf;
    int nodes;
    point(int l,int n)
    {
        leaf=l;
        nodes=n;
    }
}