import std.stdio, std.algorithm, std.range, std.conv, std.string, std.math, std.container, std.typecons;
import core.stdc.stdio;
// foreach, foreach_reverse, writeln

void main() {
	int n;
	scanf("%d", &n);
	long[] d = new long[n];
	foreach (i; 0..n) {
		scanf("%lld", &d[i]);
	}
	alias Tuple!(long,int) P;
	P[] raw_p = new P[n];
	foreach (i; 0..n) {
		raw_p[i][0] = d[i];
		raw_p[i][1] = i;
	}
	auto p = raw_p.sort.assumeSorted;
	int[] sz = new int[n];
	P[] ans;
	foreach_reverse (i; 1..n) {
		int v = p[i][1];
		sz[v]++;
		int diff = (n-sz[v]) - sz[v];
		int pi = p.lowerBound(P(d[v]-diff,-1)).length.to!int;
		if (pi == n || p[pi][0] != d[v]-diff) {
			writeln(-1);
			return;
		}
		int par = p[pi][1];
		sz[par] += sz[v];
		ans ~= P(v+1, par+1);
	}

	int[][] to = new int[][](n);
	foreach (edge; ans) {
		int a = edge[0].to!int, b = edge[1];
		if (d[a] > d[b]) swap(a,b);
		to[a] ~= b;
	}
	int root = p[0][1];
	long dfs(int v, int depth) {
		long ret = depth;
		foreach (int u; to[v]) ret += dfs(u,depth+1);
		return ret;
	}
	if (dfs(root, 0) != d[root]) {
		writeln(-1);
		return;
	}

	foreach (edge; ans) {
		writeln(edge[0], ' ', edge[1]);
	}
}