// Slower C++ solution:
/*

Though leaves are many, the root is one;

Through all the lying days of my youth

I swayed my leaves and flowers in the sun,

Now may I wither into the truth.



- William Butler Yeats

*/

#include <iostream>

#include <algorithm>

#include <math.h>

#include <string.h>

#include <cstdio>

#include <vector>

#include <set>

#include <cassert>

#include <cstdlib>

#include <complex>

#include <cctype>

#include <cmath>

#include <ctime>

#include <deque>

#include <queue>

#include <stack>

#include <map>

#include <set>

#include <sstream>

#include <functional>

#include <iomanip>

#include <bitset>

//#include <windows.h>  //Should be deleted when using AtCoder&POJ

using namespace std;



#define ll long long

#define pii pair<int,int>

#define qi ios::sync_with_stdio(0)

/**==Info==

*Program:6

*Problem:Distance Sums

*Date:2019-7-12

*Algorithm:Orange Boy's Greedy and Sorting

*Stats:WA*/



bool debug=false;





template<typename T1,typename T2> ostream& operator<<(ostream& o,pair<T1,T2> p){

	o<<"{";

	o<<p.first<<","<<p.second;

	o<<"}";

	return o;

}



ll n;

ll d[100005];

map <ll,ll> m;

pair<ll,ll> p[100005];

ll sub[100005];

ll sz[100005];

vector <pair<ll,ll> >res;

 

 int fa[100005];

 

int getFa(int x){

	if(fa[x]==x){

		return x;

	}

	return fa[x]=getFa(fa[x]);

}

 

 

void Union(int a,int b){

	if(fa[a]==fa[b]){

		return;

	}

	fa[getFa(a)]=getFa(b);

}



ll dp[100005];



ll dis[100005];



vector<int> nei[100005];



int main()

{

	ios_base::sync_with_stdio(false);

	cin>>n;

	for(ll i=0;i<n;i++)

	{

		cin>>d[i];

		if(d[i]>n*(n-1)/2){

			cout<<-1;

			return 0;

		}

		m[d[i]]=i;

		p[i].first=d[i];

		p[i].second=i;

		sz[i]=1;

	}

	sort(p,p+n);

	reverse(p,p+n);

	memset(sub,-1,sizeof(sub));

	for(ll i=0;i<n-1;i++)

	{

		ll de=p[i].first;

		ll x=p[i].second;

		sub[x]=n-sz[x]*2;

		if(sub[x]==0){

			cout<<-1;

			return 0;	

		}

		if(m.find(de-sub[x])==m.end()){

			cout<<-1;

			return 0;

		}

		ll par=m[de-sub[x]];

		sz[par]+=sz[x];

		dp[par]+=dp[x]+sz[x];

		res.push_back(make_pair(x,par));

	}

	

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

		nei[res[i].first].push_back(res[i].second);

		nei[res[i].second].push_back(res[i].first);

	}

	

	queue<int> q;

	memset(dis,-1,sizeof(dis));

	q.push(p[n-1].second);

	dis[p[n-1].second]=0;

	

	while(!q.empty()){

		int last=q.front();

		q.pop();

		

		for(int to:nei[last]){

			if(dis[to]==-1){

				dis[to]=dis[last]+1;

				q.push(to);

			}

		}

	}

	

	ll sm=0;

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

		sm+=dis[i];

	}

	if(sm!=p[n-1].first){

		cout<<-1;

		return 0;

	}

	

	for(ll i=0;i<n-1;i++)

	{

		cout<<res[i].first+1<<" "<<res[i].second+1<<endl;

	}

	

	

	return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.649381507342406x):
#include <iostream>

#include <cstdio>

#include <algorithm>

#define int long long

#define ll long long

using namespace std;

inline int read()

{

	int x = 0, f = 1; char ch = getchar();

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

	while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}

	return x * f;

}

const int N = 1e5 + 1000;

int n,num; ll dis,siz[N];

int u[N],to[N];

struct node

{

	ll v; int id;

	int friend operator <(node a,node b){return a.v < b.v;}

}p[N];

signed main()

{

	n = read();

	for(int i = 1;i <= n;i ++) {p[i] = node{read(),i}; siz[i] = 1;}

	sort(p + 1,p + 1 + n);

	for(int i = n;i > 1;i --)

	{

		ll Dis = p[i].v - n + (siz[i] << 1);

		int t = lower_bound(p + 1,p + 1 + n,node{Dis,0}) - p;

		if(p[t].v != Dis) {puts("-1"); return 0;}

		num ++; u[num] = p[i].id; to[num] = p[t].id;

		siz[t] += siz[i]; dis += siz[i]; 

	}

	if(dis != p[1].v) {puts("-1"); return 0;}

	else for(int i = 1;i < n;i ++) cout << u[i] << " " << to[i] << "\n";

}