// Slower C++ solution:
#include<bits/stdc++.h>

#define rep(i,a,b) for(int i=(a);i<=(b);i++)

#define per(i,a,b) for(int i=(a);i>=(b);i--)

#define REP(i,n) for(int i=(0);i<(n);i++)

#define fi first

#define se second

#define pb push_back

#define mp make_pair

using namespace std;

typedef pair<int,int> pii;

typedef vector<int> vi;

typedef long long ll;



template<class T> inline void read(T &x){

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

	for(;!isdigit(ch);ch=getchar())f|=(ch=='-');

	for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';

	if(f)x=-x;

}



const int N=100005;

struct node{

	ll d; int sz,id;

	friend bool operator < (node a,node b){

		return a.d<b.d;

	}

};

set<node> s;

vector<pii> ans;

int d[N],n;

ll rem;

vi e[N];



void dfs(int u,int fa){

	for(auto v:e[u])

		if(v!=fa){

			d[v]=d[u]+1;

			dfs(v,u);

		}

	rem-=d[u];

}



int main(){

	read(n);	

	rep(i,1,n){

		ll tmp; read(tmp);

		s.insert((node){tmp,1,i});

	}

	while(s.size()>=2){

		node t=*(--s.end());

		s.erase(--s.end());

		set<node>::iterator it=s.lower_bound((node){t.d-n+2*t.sz,0});

		if(it==s.end()||it->d!=t.d-n+2*t.sz)

			return puts("-1"),0;

		int x=t.id,y=it->id;

		if(x>y)swap(x,y);

		ans.pb(mp(x,y));

		node v=*it;

		v.sz+=t.sz;

		s.erase(it);

		s.insert(v);

	}

	for(auto x:ans)

		e[x.fi].pb(x.se),e[x.se].pb(x.fi);

	int rt=s.begin()->id;

	rem=s.begin()->d;

	dfs(rt,0);

	if(rem!=0)return puts("-1"),0;

	sort(ans.begin(),ans.end());

	for(auto x:ans)

		printf("%d %d\n",x.fi,x.se);

	return 0;

}

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



using namespace std;



const int maxn = 100010;



typedef long long ll;



priority_queue<ll> pq;

map<ll, int> mp;



int n, l[maxn], dep[maxn], sz[maxn], w[maxn], vis[maxn], e_u[maxn], e_v[maxn], tot, e = 0;

ll D[maxn], S[maxn];



struct Edge {

    int v, x;

} E[maxn];



inline void addEdge(int u, int v) {

    E[e].v = v; E[e].x = l[u]; l[u] = e++;

}



void dfs1(int u) {

    sz[u] = 1;

    for (int p = l[u]; p >= 0; p = E[p].x) {

        int v = E[p].v;

        dep[v] = dep[u] + 1;

        dfs1(v);

        sz[u] += sz[v];

    }

}



void dfs2(int u) {

    for (int p = l[u]; p >= 0; p = E[p].x) {

        int v = E[p].v;

        S[v] = S[u] + n - 2 * sz[v];

        dfs2(v);

    }

}



int main() {

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

    scanf("%d", &n);

    for (int i = 1; i <= n; i++) scanf("%lld", &D[i]);

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

        mp[D[i]] = i;

        pq.push(D[i]);

        w[i] = 1;

    }

    vis[0] = 1;

    while (pq.size() > 1) {

        ll v = pq.top(); pq.pop();

        int u = mp[v];

        vis[u] = 1;

        if (!vis[mp[v + 2 * w[u] - n]]) {

            int t = mp[v + 2 * w[u] - n];

            w[t] += w[u];

            addEdge(t, u);

            ++ tot;

            e_u[tot] = t; e_v[tot] = u;

        } else {

            puts("-1");

            return 0;

        }

    }

    int r = mp[pq.top()];

    dfs1(r);

    for (int i = 1; i <= n; i++) S[r] += dep[i];

    dfs2(r);

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

        if (S[i] != D[i]) {

            puts("-1");

            return 0;

        }

    }

    for (int i = 1; i <= tot; i++) printf("%d %d\n", e_u[i], e_v[i]);

    return 0;

}