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

# Lost Tree

import sys

n = int(input())

graph = {}
available_graph = {}
for x in range(1, n+1):
    graph[x] = set()

known_edges = set()

if n % 2 == 0:
    asks_left = n//2
else:
    asks_left = (n+1)//2

# print("asks left", asks_left)

def ask_info(edge, known_edges, graph):

    global asks_left
    if asks_left < 0:
        return

    # print(asks_left)

    if edge in known_edges:
        return
    
    known_edges.add(edge)
    print("? " + str(edge))
    sys.stdout.flush()

    neighbour_edges = []
    to_ask_edges = []
    for i, x in enumerate(input().split()):
        x = int(x)
        index = i + 1
        if x == 1:
            graph[edge].add(index)
            graph[index].add(edge)
            known_edges.add(index)
            neighbour_edges.append(index)
        if x == 2 and index not in known_edges:
            to_ask_edges.append(index)

    # print("graph after {}. {}".format(edge,graph))
    sys.stdout.flush()
    for x in to_ask_edges:
        if x in available_graph:
            pass
        else:
            available_graph[x] = neighbour_edges
        asks_left -= 1
        ask_info(x, known_edges, graph)
    
asks_left -= 1
ask_info(1, known_edges, graph)
# print(graph)
# print(available_graph)

for edge, neighbour_edges in available_graph.items():
    if len(graph[edge]) == 0:
        graph[edge].add(neighbour_edges[0])
        graph[neighbour_edges[0]].add(edge)

print("!")
printed_edges = set()
for edge, neighbours in graph.items():
    if edge in printed_edges:
        continue
    else:
        for neighbour in neighbours:
            if neighbour not in printed_edges:
                print(edge, neighbour)
        printed_edges.add(edge)
