// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

#pragma GCC optimize("Ofast")

typedef long long lint;

typedef unsigned int uint;

typedef pair<int, int> pii;

typedef pair<lint, lint> pll;

typedef unsigned long long ulint;

#define endl '\n'

#define fst first

#define sed second

#define pb push_back

#define mp make_pair

#define rint register int

#define newline putchar('\n')

#define leave_space putchar(' ')

#define all(x) (x).begin(), (x).end()

#define reveal(x) cerr << #x << " = " << (x) << endl

#define rep(it, f, e) for (rint it = (f); it <= (e); ++it)

#define per(it, f, e) for (rint it = (f); it >= (e); --it)

const int MAXN = 1e5 + 10;

pll p[MAXN];

int sz[MAXN];

map<lint, int> rec;

vector<int> edge[MAXN];

#define D fst

#define P sed

vector<pii> opt;

lint res = 0;

inline void dfs(int u, int par, int dep) {

	res += dep;

	for (auto v : edge[u]) {

		if (v == par) continue;

		dfs(v, u, dep + 1);

	}

}

int main() {

	ios::sync_with_stdio(false);

	cin.tie(NULL), cout.tie(NULL);

	int n;

	cin >> n;

	rep (i, 1, n) {

		cin >> p[i].D;

		p[i].P = i;

		if (rec.find(p[i].D) != rec.end()) {

			cout << -1 << endl;

			return 0;

		}

		rec[p[i].D] = p[i].P;

	}

	sort(p + 1, p + n + 1, greater<pll>());

	fill(sz + 1, sz + n + 1, 1);

	rep (i, 1, n - 1) {

		int u = p[i].P;

		if (n - sz[u] - sz[u] <= 0) {

			cout << -1 << endl;

			return 0;

		} 

		lint diff = p[i].D - (n - sz[u] - sz[u]);

		if (rec.find(diff) == rec.end()) {

			cout << -1 << endl;

			return 0;

		}

		int v = rec[diff];

		opt.pb(pii(u, v));

		edge[u].pb(v);

		edge[v].pb(u);

		sz[v] += sz[u];

	}

	dfs(p[n].P, 0, 0);

	if (res != p[n].D) {

		cout << -1 << endl;

		return 0;

	}

	for (auto &v : opt) {

		if (v.fst > v.sed) swap(v.fst, v.sed);

	}

	sort(all(opt));

	for (auto &v : opt) {

		cout << v.fst << ' ' << v.sed << endl;

	}

	return 0;

}

// Optimized solution to the same problem (faster):
#include <map>

#include <cstdio>

#include <cstring>

#include <iostream>

#include <algorithm>

using namespace std;

#define ll long long

#define N 100005

#define M 200005

map<ll, int>p;

map<ll, int>::iterator it;

int fat[N], siz[N], a[N], b[N], fir[N], nex[M], tar[M];

int n, cnt;

void Add(int a, int b)

{

	++cnt;

	tar[cnt] = b;

	nex[cnt] = fir[a];

	fir[a] = cnt;

}

ll wd[N], d[N];

void Dfs(int x, int dis)

{

    siz[x] = 1;

    d[1] += dis;

	for (int i = fir[x]; i; i = nex[i])

    {

		if (tar[i] != fat[x])

		{

			fat[tar[i]] = x;

			Dfs(tar[i], dis + 1);

			siz[x] += siz[tar[i]];

        }

    }

}

void Dfs(int x)

{

	for (int i = fir[x]; i; i = nex[i])

	{

		if (tar[i] != fat[x])

        {

            d[tar[i]] = d[x] + n - siz[tar[i]] * 2;

            Dfs(tar[i]);

        }

    }

}

int Getbel(int x)

{

	if (fat[x] == x)

		return x;

	return fat[x] = Getbel(fat[x]);

}

int main()

{

	scanf("%d",&n);

	for (int i = 1; i <= n; i++)

	{

		scanf("%lld", &wd[i]);

		p[wd[i]] = i;

	}

	for (int i = 1; i <= n; i++)

	{

		fat[i] = i;

		siz[i] = 1;

	}

	it = p.end();

	for (it--; it != p.begin(); it--)

	{

		if (n - siz[it -> second] * 2 == 0 || !p.count(it -> first - (n - siz[it -> second] * 2)))

		{

			puts("-1");

			return 0;

		}

		cnt++;

		a[cnt] = it -> second;

		b[cnt] = p[it -> first - (n - siz[it -> second] * 2)];

		siz[fat[a[cnt]] = Getbel(b[cnt])] += siz[a[cnt]];

	}

	cnt = 0;

	for (int i = 1; i < n; i++)

	{

		Add(a[i], b[i]);

		Add(b[i], a[i]);

	}

	fat[1] = 0;

	Dfs(1, 0);

	Dfs(1);

	for (int i = 1; i <= n; i++)

	{

		if (wd[i] != d[i])

		{

			puts("-1");

		    return 0;

		}

	}

	for (int i = 1; i < n; i++)

		printf("%d %d\n", a[i], b[i]);

}

// Fastest known solution for this problem: