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 os
import sys

from collections import deque

input = sys.stdin.buffer.readline


DEBUG = False


def solve():
    def debug(*args):
        if not DEBUG:
            return
        sys.stderr.write("\033[0;31m")
        print(*args, file=sys.stderr)
        sys.stderr.write("\033[0m")
        sys.stderr.flush()

    def query(*args):
        (r,) = args
        assert 0 <= r < N

        os.write(1, b"? %r\n" % (r + 1))

        dist = [int(x) for x in input().split()]
        assert len(dist) == N

        if DEBUG:
            debug("query(" + ", ".join(map(str, args)) + "):", dist)
        return dist

    def answer(graph):
        os.write(
            1,
            b"!\n%s\n"
            % (
                "\n".join(
                    str(u + 1) + " " + str(v + 1)
                    for u, nbrs in enumerate(graph)
                    for v in nbrs
                    if u > v
                ).encode()
            ),
        )

    (N,) = [int(x) for x in input().split()]

    graph = [set() for i in range(N)]

    edges = 0
    q = deque([0])
    seen = set([0])
    while q:
        u = q.popleft()
        dists = query(u)
        for v, d in enumerate(dists):
            if d == 1:
                if v not in graph[u]:
                    graph[u].add(v)
                    graph[v].add(u)
                    edges += 1
            if d == 2:
                if v not in seen:
                    seen.add(v)
                    q.append(v)
    assert edges == N - 1
    answer(graph)
    sys.stdout.flush()


if __name__ == "__main__":
    solve()
