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 collections
import functools
import math
import random
import sys
import bisect

import io, os

# input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
#
#
input = sys.stdin.readline


def In():
    return map(int, input().split())


def pf(*args, sep=' ', end='\n'):
    print(*args, sep=sep, end=end)
    sys.stdout.flush()


def losttree():
    n = int(input())
    pf('?', 1)
    back = input().split()
    p = []
    p1 = []
    for i in range(n):
        if i != 0:
            if int(back[i]) % 2:
                p1.append(i + 1)
            else:
                p.append(i + 1)
    l = [[] for _ in range(n + 1)]
    if len(p) - 1 > len(p1):
        p, p1 = p1, p
    else:
        pos = 1
        for i in back:
            if i == '1':
                l[1].append(pos)
            pos += 1
    for i in p:
        pf('?', i)
        pos = 1
        for v in input().split():
            if v == '1':
                l[i].append(pos)
            pos += 1
    pf('!')
    for i in range(1, n + 1):
        for i1 in l[i]:
            pf(i, i1)


losttree()
