#include <bits/stdc++.h>
using namespace std;
vector<vector<pair<int, int> > > adjlist;
vector<int> taken;
priority_queue<tuple<int, int, int>, vector<tuple<int, int, int> >,
               greater<tuple<int, int, int> > >
    pq;
void process(int vtx) {
  taken[vtx] = 1;
  for (int j = 0; j < (int)adjlist[vtx].size(); j++) {
    pair<int, int> v = adjlist[vtx][j];
    if (!taken[v.first]) pq.push(tuple<int, int, int>(v.second, v.first, vtx));
  }
}
int main() {
  int v, e;
  cin >> v >> e;
  vector<tuple<int, int, int> > edges;
  for (int i = 0; i < e; i++) {
    int w;
    int mst;
    cin >> w >> mst;
    edges.push_back(make_tuple(w, mst, i));
  }
  struct {
    bool operator()(tuple<int, int, int> a, tuple<int, int, int> b) const {
      if (get<0>(a) != get<0>(b))
        return get<0>(a) < get<0>(b);
      else
        return get<1>(a) > get<1>(b);
    }
  } sort_edges;
  sort(edges.begin(), edges.end(), sort_edges);
  if (get<1>(edges[0]) == 0) {
    cout << -1 << endl;
    return 0;
  }
  vector<tuple<int, int, int> > graph(e, make_tuple(-1, -1, -1));
  adjlist.resize(v);
  int msti = 1, noni = 1, nonj = 2;
  for (tuple<int, int, int> i : edges) {
    int weight = get<0>(i);
    int in_mst = get<1>(i);
    int pos = get<2>(i);
    if (in_mst == 1) {
      if (msti >= v) {
        cout << -1 << endl;
        return 0;
      }
      graph[pos] = make_tuple(0, msti, weight);
      adjlist[0].push_back(pair<int, int>(msti, weight));
      adjlist[msti].push_back(pair<int, int>(0, weight));
      ++msti;
    } else {
      if (nonj >= v) {
        cout << -1 << endl;
        return 0;
      }
      if (nonj >= msti) {
        cout << -1 << endl;
        return 0;
      }
      graph[pos] = make_tuple(noni, nonj, weight);
      adjlist[nonj].push_back(pair<int, int>(noni, weight));
      adjlist[noni].push_back(pair<int, int>(nonj, weight));
      ++noni;
      if (noni >= nonj) {
        ++nonj;
        noni = 1;
      }
    }
  }
  taken.assign(v, 0);
  process(0);
  vector<pair<int, int> > mst_map;
  while (!pq.empty()) {
    tuple<int, int, int> front = pq.top();
    pq.pop();
    int u0 = get<1>(front);
    int u1 = get<2>(front);
    if (!taken[u0]) {
      mst_map.push_back(pair<int, int>(u0, u1));
      process(u0);
    }
  }
  if (mst_map.size() != (v - 1)) {
    cout << -1 << endl;
    return 0;
  }
  for (tuple<int, int, int> i : graph) {
    cout << get<0>(i) + 1 << " " << get<1>(i) + 1 << endl;
  }
  return 0;
}
