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.*;

public class A{
    public static void main(String args[])
    {
        Scanner sc=new Scanner(System.in);
        long mod=1000000007l;
        int cases=1;

        while(cases>0)
        {
            cases--;
            int n=sc.nextInt();
            boolean touched[]=new boolean[n];
            boolean abs[]=new boolean[n];
            StringBuilder ans=new StringBuilder();
            Map<String,Integer> map=new HashMap<>();

            int l=(n+1)/2;
            int tot=0;
            for(int j=0;j<n;j++)
            {
                if(touched[j]==false)
                {
                    touched[j]=true;
                    abs[j]=true;
                    System.out.println("? "+(j+1));
                    l--;
                    if(l<0)
                    {
                        while(true)
                        {

                        }
                    }
                    System.out.flush();
                    int dis[]=new int[n];
                    int far[]=new int[n];
                    Map<Integer,Integer> nodes=new HashMap<>();
                    for(int k=0;k<n;k++)
                    {
                        dis[k]=sc.nextInt();
                        nodes.put(dis[k],k);
                        far[dis[k]]++;

                    }

                    int c=1;
                    int now=j;
                    while(c!=n&&far[c]==1)
                    {

                        if(map.get((now+1)+" "+(nodes.get(c)+1))==null) {
                            ans.append((now + 1) + " " + (nodes.get(c) + 1)+"\n");
                            map.put((now + 1) + " " + (nodes.get(c) + 1), 1);
                            map.put((nodes.get(c) + 1) + " " + (now + 1), 1);
                            tot++;
                        }
                        touched[now]=true;
                        abs[now]=true;
                        now=nodes.get(c);
                        touched[now]=true;
                        abs[now]=true;

                        c++;
                    }

                    for(int k=0;k<n;k++)
                    {
                        if(dis[k]==c)
                        {
                            if(map.get((now+1)+" "+(k+1))==null) {
                                ans.append((now + 1) + " " + (k+ 1)+"\n");
                                map.put((now + 1) + " " + (k + 1), 1);
                                map.put((k + 1) + " " + (now + 1), 1);
                                tot++;
                            }

                            touched[k]=true;
                        }
                    }

//                    for(int k=0;k<n;k++)
//                    {
//                        if(tot!=n-1&&abs[k]==false)
//                        {
//
//                        }
//                    }


                }
            }

            for(int j=0;j<n;j++)
            {
                if(tot!=n-1&&abs[j]==false)
                {
                    System.out.println("? "+(j+1));
                    l--;
                    if(l<0)
                    {
                        
                    }
                    System.out.flush();
                    int dis[]=new int[n];
                    int far[]=new int[n];
                    Map<Integer,Integer> nodes=new HashMap<>();
                    for(int k=0;k<n;k++)
                    {
                        dis[k]=sc.nextInt();
                        nodes.put(dis[k],k);
                        far[dis[k]]++;

                    }

                    int c=1;
                    int now=j;
                    while(c!=n&&far[c]==1)
                    {

                        if(map.get((now+1)+" "+(nodes.get(c)+1))==null) {
                            ans.append((now + 1) + " " + (nodes.get(c) + 1)+"\n");
                            map.put((now + 1) + " " + (nodes.get(c) + 1), 1);
                            map.put((nodes.get(c) + 1) + " " + (now + 1), 1);
                            tot++;
                        }
                        touched[now]=true;
                        abs[now]=true;
                        now=nodes.get(c);
                        touched[now]=true;
                        abs[now]=true;

                        c++;
                    }

                    for(int k=0;k<n;k++)
                    {
                        if(dis[k]==c)
                        {
                            if(map.get((now+1)+" "+(k+1))==null) {
                                ans.append((now + 1) + " " + (k+ 1)+"\n");
                                map.put((now + 1) + " " + (k + 1), 1);
                                map.put((k + 1) + " " + (now + 1), 1);
                                tot++;
                            }

                            touched[k]=true;
                        }
                    }

//                    for(int k=0;k<n;k++)
//                    {
//                        if(tot!=n-1&&abs[k]==false)
//                        {
//
//                        }
//                    }


                }
            }
            System.out.println("!");
            System.out.println(ans);

            //0 1 2 3 2 3 1 2 1 2
            //2 1 0 1 2 3 3 4 3 4
            //2 1 2 3 0 1 3 4 3 4
            //2 3 4 5 4 5 1 0 3 4
            //2 3 4 5 4 5 3 4 1 0


            //0 3 1 1 4 2
            //3 0 2 4 1 1

        }

    }
}
