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

public class Main {
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
	static String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}
	static int readInt() throws IOException {
		return Integer.parseInt(next());
	}
	static long readLong() throws IOException {
		return Long.parseLong(next());
	}
	static double readDouble() throws IOException {
		return Double.parseDouble(next());
	}
	static char readChar() throws IOException {
		return next().charAt(0);
	}
	static String readLine() throws IOException {
		return br.readLine();
	}
	static class Pair implements Comparable<Pair> {
		int f, s;
		Pair(int f, int s) {
			this.f = f; this.s = s;
		}
		public int compareTo(Pair other) {
			if (this.f != other.f) return this.f - other.f;
			return this.s - other.s;
		}
	}
	static int n, p[], dis[][];
	static boolean vis[];
	static void query(int idx, int a[]) throws IOException {
		System.out.println("? " + idx);
		System.out.flush();
		for (int i = 1; i <= n; ++i) a[i] = readInt();
	}
	static void DFS(int v, int g) throws IOException {
		vis[v] = true;
		if (g != 0) {
			query(v, dis[v]);
			for (int u = 1; u <= n; ++u)
				if (dis[v][u] == 1 && dis[g][u] == 1) p[v] = u;
			for (int u = 1; u <= n; ++u) {
				if (dis[v][u] == dis[g][u]) dis[p[v]][u] = dis[v][u] - 1;
				else dis[p[v]][u] = Math.min(dis[v][u], dis[g][u]) + 1;
			}
		}
		for (int u = 1; u <= n; ++u) {
			if (dis[v][u] == 1 && u != p[v]) {
				p[u] = v;
				vis[u] = true;
			}
		}
		if (g != 0) DFS(p[v], 0);
		for (int u = 1; u <= n; ++u)
			if (!vis[u] && (v == 1 || dis[p[v]][u] == dis[v][u] + 1) && dis[v][u] == 2) DFS(u, v);
	}
	public static void main(String[] args) throws IOException {
		n = readInt();
		dis = new int[n + 1][n + 1];
		p = new int[n + 1];
		vis = new boolean[n + 1];
		query(1, dis[1]);
		DFS(1, 0);
		System.out.println("!");
		for (int i = 2; i <= n; ++i)
			System.out.println(p[i] + " " + i);
		System.out.flush();
	}
}
