#include <bits/stdc++.h>

#define FOR(i,a,b) for(ll i = (a); i < (ll)(b); i++)
#define REP(i,n) FOR(i,0,n)
#define YYS(x,arr) for(auto& x:arr)
#define PW(x) (1LL<<(x))
#define SZ(x) ((ll)(x).size())

#define pb emplace_back
#define fi first
#define se second

using namespace std;

using ld = long double;
using ll = long long int;

const ll INF = (ll)1e9 + 10;
const ll INFLL = (ll)1e18 + 10;
const ll MOD = 1000000007;
     
template<class T> T &chmin( T &a , const T &b ){ return a = min(a,b); }
template<class T> T &chmax( T &a , const T &b ){ return a = max(a,b); }
template<class T> void UNIQUE(vector<T> &a){ a.erase(unique(a.begin(), a.end()), a.end()); }

template<class S, class T> ostream& operator << (ostream& os, const pair<S, T> v){
  os << "(" << v.first << ", " << v.second << ")"; return os;
}
template<class T> ostream& operator << (ostream& os, const vector<T> v){
  for(int i = 0; i < v.size(); i++){if(i > 0){os << " ";} os << v[i];} return os;
}
template<class T> ostream& operator << (ostream& os, const vector<vector<T>> v){
  for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}

ll in(){long long int x; assert(scanf("%lld", &x) == 1); return x;}
ld fin(){double x; assert(scanf("%lf", &x) == 1); return x;}
char yuyushiki[1000010]; string stin(){assert(scanf("%s", yuyushiki) == 1); return yuyushiki;}

// head

template<typename T, const T INFT>
struct Dijkstra{
  typedef pair<int,T> pit;
  typedef pair<T,int> pti;  
  vector<vector<pit>> G;
  vector<T> dist;
  int n;
  void init(int arg_n){
    n = arg_n;
    G.assign(n, vector<pit>(0));
  }
  void add_biedge(int fr, int to, T co){
    G[fr].pb(to, co);
    G[to].pb(fr, co);
  }
  void add_edge(int fr, int to, T co){
    G[fr].pb(to, co);
  }
  T dijkstra(int s, int t = -1){
    dist = vector<T>(n, INFT);
    dist[s] = 0;
    priority_queue<pti,vector<pti>,greater<pti>> que;
    que.emplace(0, s);
    while(!que.empty()){
      T d = que.top().fi;
      int p = que.top().se;
      que.pop();
      if(d > dist[p]){
	continue;
      }
      if(p == t){
	return d;
      }
      YYS(w, G[p]){
	int to = w.fi;
	T co = w.se;
	if(d + co < dist[to]){
	  dist[to] = d + co;
	  que.emplace(dist[to], to);
	}
      }
    }
    return INFT;
  }
};

Dijkstra<ll, INFLL> dij;

using pl = pair<ll, ll>;
vector<ll> G[100010];

int main(){

  ll n = in();
  vector<ll> a(n);
  REP(i, n){
    a[i] = in();
  }
  vector<ll> s(n, 1);
  vector<pl> q(0);
  REP(i, n){
    q.pb(a[i], i);
  }
  sort(q.begin(), q.end());
  reverse(q.begin(), q.end());
  map<ll, vector<pl>> call;
  dij.init(n);
  YYS(w, q){
    ll i = w.se;
    if(call.find(a[i]) != call.end()){
      YYS(c, call[a[i]]){
        // cout << "M " << i << " " << c.fi << endl;
        G[i].pb(c.fi);
        dij.add_biedge(i, c.fi, 1);
        s[i] += c.se;
      }
    }
    ll target = a[i] + s[i] - (n - s[i]);
    // cout << "T " << i << " " << target << endl;
    if(call.find(target) == call.end()){
      call[target] = vector<pl>(0);
    }
    call[target].pb(i, s[i]);
  }

  bool ok = false;
  ll pos = -1;
  REP(i, n){
    if(s[i] == n){
      ok = true;
      pos = i;
    }
  }

  if(pos != -1){
    dij.dijkstra(pos);

    ll s = 0;
    REP(i, n){
      s += dij.dist[i];
    }

    if(s != a[pos]){
      ok = false;
    }
  }
  
  if(ok){
    ll cnt = 0;
    REP(i, n){
      YYS(w, G[i]){
        cnt++;
        printf("%lld %lld\n", i+1, w+1);
      }
    }
    assert(cnt == n-1);
  } else {
    puts("-1");
  }
  
  return 0;
}


Measured memory_bytes: 28784