// Slower C++ solution:
#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;

}

// Faster C++ solution for the same problem (measured speedup: 3.538410356696503x):
#include<bits/stdc++.h>

using namespace std;

const int N=2e5+3;

int n,siz[N],he[N],e;

long long anss;

struct syzs{

	long long val;

	int num;

} a[N];

struct ans{

	int e1,e2;

	bool operator <(const ans &emm) const{

	    if(emm.e1==e1) return e2>emm.e2;

		return emm.e1<e1;

	}

};

struct edg{

	int ne,to;

} edg[N];

bool cmp(syzs c,syzs b){

	return c.val>b.val;

}

int find(int k){

	long long chec=2*siz[k]-n;

	for(int i=k+1;i<=n;i++) if(a[i].val-a[k].val==chec) return i;

	return -1;

}

long long read(){

	long long s=0,f=1;

	char ch=getchar();

	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}

	while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}

	return s*f;

}

void add(int u,int v){

	edg[++e].to=v;

	edg[e].ne=he[u];

	he[u]=e;

}

void test(int u,int fa,int dep){

	anss+=dep;

	for(int i=he[u];i;i=edg[i].ne){

		int v =edg[i].to;

		if(v==fa) continue;

		test(v,u,dep+1);

	}

}

int main(){

    priority_queue <ans> q;

	cin>>n;

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

		a[i].val=read();//scanf("%lld",&a[i].val);

		a[i].num=i;

		siz[i]=1;

	}

	sort(a+1,a+n+1,cmp);

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

		int v=find(i);

		if(v==-1){

			cout<<-1<<endl;

			return 0;

		}

		siz[v]+=siz[i];

		add(a[i].num,a[v].num);

		add(a[v].num,a[i].num);

		q.push((ans) {min(a[v].num,a[i].num),max(a[v].num,a[i].num)});

	}

	test(a[1].num,0,0);

	if(anss!=a[1].val){

		cout<<-1<<endl;

		return 0;

	}

	while(!q.empty()){

		int v1=q.top().e1,v2=q.top().e2;

    	q.pop();

    	printf("%d %d\n",v1,v2);

	}

}