//#include <bits/stdc++.h>
#include <iostream>
#include <cmath>
/*
 *STL headers
 */
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <string>

using namespace std;

#define LLI				long long int
#define PN 				cout<<'\n'

#define SZ(a) 			int((a).size())
#define PB 				push_back
#define ALL(c) 			(c).begin(),(c).end()
#define FORITER(i,c)	for(typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define CFIND(x,c) 		((c).find(x) != (c).end())
#define FIND(x,c) 		(find(ALL(c),x) != (c).end())

#define PI 			    3.1415926535
#define MOD				1000000007

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int n, r, c;
	int m;
	cin>>n>>m;
	int i = 0;
	vector<tuple<int, int, int>> v(m);
	while(i < m){
		cin>>r>>c;
		v[i] = make_tuple(r, -c, i);
		i++;
	}

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

	vector<tuple<int, int, int>> connected;
	vector<int> loop_indices;
	LLI loops = 0, node = 1;
	for(int i = 0; i < m; ++i){
		cout<<get<0>(v[i])<<" "<<get<1>(v[i]);PN;
		if(get<1>(v[i]) == -1){
			connected.push_back(make_tuple(get<2>(v[i]) + 1, (int)(node), (int)node + 1));
			node++;
		}
		else{
			loops++;
			if(((node - 2)*(node  - 1)) / 2 < loops){
				cout<<-1;
				return 0;
			}
			loop_indices.push_back(get<2>(v[i]) + 1);
		}
	}
	// cout<<loop_indices.size();PN;
	int ind = 0;
	for(int i = 2; i <= n - 1; ++i){
		for(int j = 1; j + i <= n; ++j){
			if(ind == (int)loop_indices.size())
				break;
			connected.push_back(make_tuple(loop_indices[ind], j, j+i));
			ind++;
		}
		if(ind == (int)loop_indices.size())
				break;
	}
	PN;PN;
	sort(connected.begin(), connected.end());
	for(auto e: connected){
		cout<<get<1>(e)<<" "<<get<2>(e);PN;
	}

	return 0;
}


//#include <bits/stdc++.h>
#include <iostream>
#include <cmath>
/*
 *STL headers
 */
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <iterator>
#include <algorithm>
#include <numeric>
#include <string>

using namespace std;

#define LLI				long long int
#define PN 				cout<<'\n'

#define SZ(a) 			int((a).size())
#define PB 				push_back
#define ALL(c) 			(c).begin(),(c).end()
#define FORITER(i,c)	for(typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define CFIND(x,c) 		((c).find(x) != (c).end())
#define FIND(x,c) 		(find(ALL(c),x) != (c).end())

#define PI 			    3.1415926535
#define MOD				1000000007

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int n, r, c;
	int m;
	cin>>n>>m;
	int i = 0;
	vector<tuple<int, int, int>> v(m);
	while(i < m){
		cin>>r>>c;
		v[i] = make_tuple(r, -c, i);
		i++;
	}

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

	vector<tuple<int, int, int>> connected;
	vector<int> loop_indices;
	LLI loops = 0, node = 1;
	for(int i = 0; i < m; ++i){
		if(get<1>(v[i]) == -1){
			connected.push_back(make_tuple(get<2>(v[i]) + 1, (int)(node), (int)node + 1));
			node++;
		}
		else{
			loops++;
			if(((node - 2)*(node  - 1)) / 2 < loops){
				cout<<-1;
				return 0;
			}
			loop_indices.push_back(get<2>(v[i]) + 1);
		}
	}
	// cout<<loop_indices.size();PN;
	int ind = 0;
	for(int i = 1; i <= n; ++i){
		for(int j = i+2; j <= n; ++j){
			if(ind == (int)loop_indices.size())
				break;
			connected.push_back(make_tuple(loop_indices[ind], i, j));
			ind++;
		}
		if(ind == (int)loop_indices.size())
				break;
	}
	sort(connected.begin(), connected.end());
	for(auto e: connected){
		cout<<get<1>(e)<<" "<<get<2>(e);PN;
	}

	return 0;
}


#include <cstring>
#include <map>
#include <deque>
#include <queue>
#include <stack>
#include <sstream>
#include <numeric>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <fstream>
#include <string>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <algorithm>
#include <vector>
#include <set>
#include <complex>
#include <list>
#include <climits>
#include <cctype>
#include <bitset>
using namespace std;

#define PI 3.14159265359
#define all(v) v.begin(),v.end()
#define sortva(v) sort(all(v))
#define sortvd(v) sort(v.rbegin(),v.rend())
#define sortaa(a,n) sort(a,a+n)
#define sortad(a,n) sort(a,a+n),reverse(a,a+n)
#define sfi1(v) scanf("%d",&v)
#define sfi2(v1,v2) scanf("%d %d",&v1,&v2)
#define sfi3(v1,v2,v3) scanf("%d %d %d",&v1,&v2,&v3)
#define sfll1(v) scanf("%I64d",&v);
#define sfll2(v1,v2) scanf("%I64d %I64d",&v1,&v2)
#define sfll3(v1,v2,v3) scanf("%I64d %I64d %I64d",&v1,&v2,&v3)
#define sfstr(v) scanf("%s", v);
#define sz(v) (int)v.size()
#define ndl puts("")
#define SS stringstream
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

int dx[] = { 0, 0, 1, -1, 1, -1, 1, -1 };
int dy[] = { 1, -1, 0, 0, -1, 1, 1, -1 };

ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return (a / gcd(a, b)) * b; }

void PLAY() {
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	cout << fixed << setprecision(10);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}

int main() {
	PLAY();

	int n, m;
	cin >> n >> m;
	vector<pair<pair<int, int>, int>> edges(m);

	for (int i = 0; i < m; i++) {
		cin >> edges[i].first.first;
		cin >> edges[i].first.second;
		edges[i].second = i;
		edges[i].first.second *= -1;
	}

	sortva(edges);
	vector<pair<int, int>> res(m);
	int p1 = 2, p2 = 3, p3 = 2;
	for (int i = 0; i < m; i++) {
		if (edges[i].first.second)
			res[edges[i].second] = { 1, p1++ };
		else {
			if (p3 == 1) {
				p2++;
				p3 = p2 - 1;
			}
			if (p2 >= p1 || p3 == 1) {
				cout << -1 << endl;
				return 0;
			}
			res[edges[i].second] = { p2, p3 };
			p3--;
		}
	}
	for (int i = 0; i < m; i++)
		cout << res[i].first << " " << res[i].second << endl;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int OO = (int) 1e9;
const double eps = 1e-15;

#define db(x) 			cout<<"> "<<(#x)<<" = "<<(x)<<'\n'
#define db2(x,y) 		cout<<"> "<<(#x)<<" = "<<(x)<<", "<<(#y)<<" = "<<(y)<<'\n'
#define db3(x,y,z) 		cout<<"> "<<(#x)<<" = "<<(x)<<", "<<(#y)<<" = "<<(y)<<", "<<(#z)<<" = "<<(z)<<'\n'
#define trav(a,x) 		for(auto&a:x)
#define lp(i,n) 		for(int i=0;i<int(n);++i)
#define lpi(i,j,n) 		for(int i=j;i<int(n);++i)
#define lpd(i,j,n) 		for(int i=j;i>=int(n);--i)
#define ndl 			cout<<'\n'
#define all(v) 			v.begin(),v.end()
#define rall(v) 		v.rbegin(),v.rend()
#define present(a,x) 	(a.find(x)!=a.end())
#define cpresent(a,x) 	(find(all(a),x)!=a.end())
#define sz(v) 			int(v.size())
#define clr(v, d) 		memset(v,d,sizeof(v))
#define pb 				push_back
#define mp 				make_pair
#define fs 				first
#define sc 				second

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
typedef vector<vector<int> > vvi;
typedef map<int, int> mii;
typedef set<int> si;

int n,m,w,type,nxt[100005],curr=1,idx,setSz=1;
vii ans(100005);
vector<pair<int,pair<bool,int>>>edges;
stringstream out;

int main() {
	ios::sync_with_stdio(false);
	cout.precision(15);
	cin>>n>>m;
	lp(i,m){
		cin>>w>>type;
		edges.pb(mp(w,mp(!type,i)));
	}
	lp(i,n)
		nxt[i]=1;
	sort(all(edges));
	lp(i,m){
		w=edges[i].fs,type=edges[i].sc.fs,idx=edges[i].sc.sc;
		if (!type)
			ans[idx]=mp(0,setSz++);
		else{
			if (nxt[curr]==curr)
				++curr;
			if (curr>=setSz)
				{cout<<"-1\n";	return 0;}
			ans[idx]=mp(curr,nxt[curr]++);
		}
	}
	lp(i,m)
		out<<ans[i].fs+1<<' '<<ans[i].sc+1<<'\n';
	cout<<out.str();
	return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
#include <math.h>
#include <map>
#define INF 999999999
#define N 100005
/*mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#include <random>
#include <chrono>*/

using namespace std;
const int MAX = 999999999;

struct Edge{
    int to;
    int dis;
    int next;
} edges[210000];

int cur[10010], head[10010], edge_num = -1;
int n, m, s, t;

void addEdge2(int from, int to, int dis){
    edges[++edge_num].to = to;
    edges[edge_num].dis = dis;
    edges[edge_num].next = head[from];
    head[from] = edge_num;
}

void addEdge(int from, int to, int dis){
    addEdge2(from, to, dis), addEdge2(to, from, 0);
    //cout<<from<<" "<<to<<" "<<dis<<endl;
}

int d[10010];

int DFS(int u, int flow){
    if (u == t) return flow;
    int _flow = 0, __flow;
    for (int& c_e = cur[u]; c_e != -1; c_e = edges[c_e].next){
        int v = edges[c_e].to;
        if (d[v] == d[u] + 1 && edges[c_e].dis > 0){
            __flow = DFS(v, min(flow, edges[c_e].dis));
            flow -= __flow;
            edges[c_e].dis -= __flow;
            _flow += __flow;
            edges[c_e^1].dis += __flow;
            if (!flow)
                break;
        }
    }
    if (!_flow) d[u] = -1;
    return _flow;
}

bool BFS(){
    int i=0;while(i<=n)
    {
        d[i]=-1;
        i++;
    }
    queue<int> que; que.push(s);
    d[s] = 0; int u, _new;
    while (!que.empty()){
        u = que.front(), que.pop();
        for (int c_e = head[u]; c_e != -1; c_e = edges[c_e].next){
            _new = edges[c_e].to;
            if (d[_new] == -1 && edges[c_e].dis > 0){
                d[_new] = d[u] + 1;
                que.push(_new);
            }
        }
    }
    return (d[t] != -1);
}

void dinic(){
    int max_flow = 0;
    while (BFS()){
        for (int i = 1; i <= n; ++i) cur[i] = head[i];
        max_flow += DFS(s, MAX);
    }
    printf("%d\n", max_flow);
}
int fa[200005];

int find(int x) {
    if(fa[x]!=x)
    {

        fa[x]=find(fa[x]);
    }
    return fa[x];
}
void join(int x, int y) {
    int px = find(x);
    int py = find(y);
    if (px != py)
    {
        fa[px] = py;
    }
}
struct path
{
    int u,v;
    double w;
};
path pp[10005];
int top;
int cmp(path a,path b)
{
    return a.w<b.w;
}
int kx[10005];
int ky[10005];
double getdis(int a,int b)
{
    return sqrt(1.0*(kx[a]-kx[b])*(kx[a]-kx[b])+(ky[a]-ky[b])*(ky[a]-ky[b]));
}
struct zh
{
    int val;
    int bj;
    int wz;
};
zh a[100005];
int cmpp(zh a,zh b)
{
    return a.val<b.val;
}
int dax[100005];
int day[100005];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int i=1;while(i<=m)
    {
        scanf("%d%d",&a[i].val,&a[i].bj);
        a[i].wz=i;
        i++;
    }
    sort(a+1,a+1+m,cmpp);
    int now=1;
    int hjx=1;
    int hjy=3;
    int f1=1;
    i=1;while(i<=m)
    {
        int temp=a[i].wz;
        if(a[i].bj==1)
        {
            dax[temp]=now;
            day[temp]=now+1;
            now++;
        }
        else
        {
            if(hjy<=now)
            {
                dax[temp]=hjx;
                day[temp]=hjy;
                if(hjx==hjy-2)
                {
                    hjy++;
                    hjx=1;
                }
                else
                    hjx++;
            }
            else
            {
                f1=0;
                break;
            }
        }
        i++;
    }
    if(f1==0) cout<<-1<<endl;
    else
    {
        int i=1;while(i<=m)
        {
            printf("%d %d\n",dax[i],day[i]);
            i++;
        }
    }
    return 0;
}


#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>
#include <string>
#include <math.h>
#include <map>
#define INF 999999999
#define N 100005
/*mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#include <random>
#include <chrono>*/

using namespace std;
const int MAX = 999999999;

struct Edge{
    int to;
    int dis;
    int next;
} edges[210000];

int cur[10010], head[10010], edge_num = -1;
int n, m, s, t;

void addEdge2(int from, int to, int dis){
    edges[++edge_num].to = to;
    edges[edge_num].dis = dis;
    edges[edge_num].next = head[from];
    head[from] = edge_num;
}

void addEdge(int from, int to, int dis){
    addEdge2(from, to, dis), addEdge2(to, from, 0);
    //cout<<from<<" "<<to<<" "<<dis<<endl;
}

int d[10010];

int DFS(int u, int flow){
    if (u == t) return flow;
    int _flow = 0, __flow;
    for (int& c_e = cur[u]; c_e != -1; c_e = edges[c_e].next){
        int v = edges[c_e].to;
        if (d[v] == d[u] + 1 && edges[c_e].dis > 0){
            __flow = DFS(v, min(flow, edges[c_e].dis));
            flow -= __flow;
            edges[c_e].dis -= __flow;
            _flow += __flow;
            edges[c_e^1].dis += __flow;
            if (!flow)
                break;
        }
    }
    if (!_flow) d[u] = -1;
    return _flow;
}

bool BFS(){
    int i=0;while(i<=n)
    {
        d[i]=-1;
        i++;
    }
    queue<int> que; que.push(s);
    d[s] = 0; int u, _new;
    while (!que.empty()){
        u = que.front(), que.pop();
        for (int c_e = head[u]; c_e != -1; c_e = edges[c_e].next){
            _new = edges[c_e].to;
            if (d[_new] == -1 && edges[c_e].dis > 0){
                d[_new] = d[u] + 1;
                que.push(_new);
            }
        }
    }
    return (d[t] != -1);
}

void dinic(){
    int max_flow = 0;
    while (BFS()){
        for (int i = 1; i <= n; ++i) cur[i] = head[i];
        max_flow += DFS(s, MAX);
    }
    printf("%d\n", max_flow);
}
int fa[200005];

int find(int x) {
    if(fa[x]!=x)
    {

        fa[x]=find(fa[x]);
    }
    return fa[x];
}
void join(int x, int y) {
    int px = find(x);
    int py = find(y);
    if (px != py)
    {
        fa[px] = py;
    }
}
struct path
{
    int u,v;
    double w;
};
path pp[10005];
int top;
int cmp(path a,path b)
{
    return a.w<b.w;
}
int kx[10005];
int ky[10005];
double getdis(int a,int b)
{
    return sqrt(1.0*(kx[a]-kx[b])*(kx[a]-kx[b])+(ky[a]-ky[b])*(ky[a]-ky[b]));
}
struct zh
{
    int val;
    int bj;
    int wz;
};
zh a[100005];
int cmpp(zh a,zh b)
{
    if(a.val==b.val)
        return a.bj>b.bj;
    return a.val<b.val;
}
int dax[100005];
int day[100005];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int i=1;while(i<=m)
    {
        scanf("%d%d",&a[i].val,&a[i].bj);
        a[i].wz=i;
        i++;
    }
    sort(a+1,a+1+m,cmpp);
    int now=1;
    int hjx=1;
    int hjy=3;
    int f1=1;
    i=1;while(i<=m)
    {
        int temp=a[i].wz;
        if(a[i].bj==1)
        {
            dax[temp]=now;
            day[temp]=now+1;
            now++;
        }
        else
        {
            if(hjy<=now)
            {
                dax[temp]=hjx;
                day[temp]=hjy;
                if(hjx==hjy-2)
                {
                    hjy++;
                    hjx=1;
                }
                else
                    hjx++;
            }
            else
            {
                f1=0;
                break;
            }
        }
        i++;
    }
    if(f1==0) cout<<-1<<endl;
    else
    {
        int i=1;while(i<=m)
        {
            printf("%d %d\n",dax[i],day[i]);
            i++;
        }
    }
    return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
using namespace std;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef pair<ii, int> iii;
typedef vector<iii> viii;
typedef vector<ii> vii;

bool comp(iii a, iii b) {
	if (a.F.F < b.F.F) return true;
	else if (a.F.F > b.F.F) return false;
	else return a.F.S > b.F.S;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n, m;
	cin>>n>>m;
	viii V(m);
	for (int i=0;i<m;++i) {
		cin>>V[i].F.F>>V[i].F.S;
		V[i].S = i;
	}
	sort(V.begin(), V.end(), comp);
	if (V[0].F.S == 0) {
		cout<<"-1\n";
		return 0;
	}
	int k = 1, cur = 1;
	vi node(n);
	vii ans(m);
	for (int i=0;i<m;++i) {
		if (V[i].F.S == 1) {
			ans[V[i].S] = ii(cur, cur+1);
			cur++;
			k = 0;
		} else {
			if (node[k] == 0) node[k] = k+2;
			if (node[k] >= cur) {
				cout<<"-1\n";
				return 0;
			}
			ans[V[i].S] = ii(k+1, node[k]+1);
			node[k]++;
			if (node[k] >= cur) k = (k+1)%cur;
		}
	}
	for (int i=0;i<m;++i) {
		cout<<ans[i].F<<" "<<ans[i].S<<"\n";
	}
	return 0;
}


#include<bits/stdc++.h>
#define F first
#define S second
using namespace std;
typedef vector<int> vi;
typedef pair<int, int> ii;
typedef pair<ii, int> iii;
typedef vector<iii> viii;
typedef vector<ii> vii;

bool comp(iii a, iii b) {
	if (a.F < b.F) return true;
	else if (a.F > b.F) return false;
	else return a.S > b.S;
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	int n, m;
	cin>>n>>m;
	viii V(m);
	for (int i=0;i<m;++i) {
		cin>>V[i].F.F>>V[i].F.S;
		V[i].S = i;
	}
	sort(V.begin(), V.end(), comp);
	if (V[0].F.S == 0) {
		cout<<"-1\n";
		return 0;
	}
	int k = 1, cur = 1;
	vi node(n);
	vii ans(m);
	for (int i=0;i<m;++i) {
		if (V[i].F.S == 1) {
			ans[V[i].S] = ii(cur, cur+1);
			cur++;
			k = 0;
		} else {
			if (node[k] == 0) node[k] = k+2;
			if (node[k] >= cur) {
				cout<<"-1\n";
				return 0;
			}
			ans[V[i].S] = ii(k+1, node[k]+1);
			node[k]++;
			if (node[k] >= cur) k = (k+1)%cur;
		}
	}
	for (int i=0;i<m;++i) {
		cout<<ans[i].F<<" "<<ans[i].S<<"\n";
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXN=0;

bool possible=true;
int N,M,cur=1,cur2=3,cur3=1;
vector<pair<pair<int,int>,int> > E;
vector<pair<int,pair<int,int> > > ans;

int main() {
	rii(N,M);
	FOR(i,0,M) {
		int w,in;rii(w,in);
		E.pb({{w,1-in},i});
	}
	sort(E.begin(),E.end());
	FOR(i,0,M) {
		int w = E[i].first.first;
		int out = E[i].first.second;
		int pos = E[i].second;
		if(!out) {
			ans.pb({pos,{cur,cur+1}});
			cur++;
		} else {
			if(cur2>cur) possible=false;
			ans.pb({pos,{cur2,cur3}});
			cur3++;
			if(cur3==cur2-1) cur2++, cur3=1;
		}
	}
	sort(ans.begin(),ans.end());
	if(possible) FOR(i,0,ans.size()) printf("%d %d\n",ans[i].second.first,ans[i].second.second);
	else printf("-1\n");
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXN=0;

bool possible=true;
int N,M,cur=1,cur2=2,cur3=1;
vector<pair<pair<int,int>,int> > E;
vector<pair<int,pair<int,int> > > ans;

int main() {
	rii(N,M);
	FOR(i,0,M) {
		int w,in;rii(w,in);
		E.pb({{w,1-in},i});
	}
	sort(E.begin(),E.end());
	FOR(i,0,M) {
		int w = E[i].first.first;
		int out = E[i].first.second;
		int pos = E[i].second;
		if(!out) {
			ans.pb({pos,{cur,cur+1}});
			cur++;
		} else {
			if(cur2>cur) possible=false;
			ans.pb({pos,{cur2,cur3}});
			cur3++;
			if(cur3==cur2) cur2++, cur3=1;
		}
	}
	sort(ans.begin(),ans.end());
	if(possible) FOR(i,0,ans.size()) printf("%d %d\n",ans[i].second.first,ans[i].second.second);
	else printf("-1\n");
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;

#define pb push_back
#define ri(x) scanf("%d",&x)
#define rii(x,y) ri(x),ri(y)
#define ms(obj,val) memset(obj,val,sizeof(obj))
#define ms2(obj,val,sz) memset(obj,val,sizeof(obj[0])*sz)
#define FOR(i,f,t) for(int i=f;i<(int)t;i++)
#define FORR(i,f,t) for(int i=f;i>(int)t;i--)

typedef long long ll;
typedef vector<int> vi;

const int MAXN=0;

bool possible=true;
int N,M,cur=1,cur2=2,cur3=1;
vector<pair<int,int> > E,ans;

int main() {
	rii(N,M);
	FOR(i,0,M) {
		int w,in;rii(w,in);
		E.pb({w,1-in});
	}
	sort(E.begin(),E.end());
	FOR(i,0,M) {
		int w = E[i].first;
		int out = E[i].second;
		if(!out) {
			ans.pb({cur,cur+1});
			cur++;
		} else {
			if(cur2>cur) possible=false;
			ans.pb({cur2,cur3});
			cur3++;
			if(cur3==cur2) cur2++, cur3=1;
		}
	}
	if(possible) FOR(i,0,ans.size()) printf("%d %d\n",ans[i].first,ans[i].second);
	else printf("-1\n");
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
int n,m;
LL cost = 0 , w = 0;
vector<pair<int,int>> ans;
vector<pair <pair<int,int>,int> > v;
int main (){
    ios_base :: sync_with_stdio(0);
    cin . tie (0) , cout . tie (0);
    cin >> n >> m ;
    int last = 1;
    int other = 1;
    int nextOther = 3;
    ans.resize(m);
    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        v . emplace_back(make_pair(u,b),i);
    }

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

    for (auto cur : v) {
        int  w = cur . first . first;
        int  b = cur . first . second ;
        int  i = cur . second ;
        //cout << w << " "<< b << " "<< i << endl;
        if ( b ) {
            ans [i] = {last,last + 1};
            last++;
        }else {
            ans[i] = { other , nextOther};
            if (nextOther > last  ){
                cout << -1 << "\n";
                return  0;
            }
            nextOther++;
            if (nextOther == n + 1){
                other ++;
                nextOther = other + 2 ;
            }
        }
    }
    for (auto cur : ans ){
        cout << cur.first << " " << cur.second << "\n";
    }

    return 0;
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
int n,m;
LL cost = 0 , w = 0;
vector<pair<int,int>> ans;
vector<pair <pair<int,int>,int> > v;
int main (){
    ios_base :: sync_with_stdio(0);
    cin . tie (0) , cout . tie (0);
    cin >> n >> m ;
    int last = 1;
    int other = 1;
    int nextOther = 3;
    ans.resize(m);
    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        v . emplace_back(make_pair(u,-b),i);
    }

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

    for (auto cur : v) {
        int  w = cur . first . first;
        int  b = cur . first . second ;
        int  i = cur . second ;
        //cout << w << " "<< b << " "<< i << endl;
        if ( b ) {
            ans [i] = {last,last + 1};
            last++;
        }else {
            ans[i] = { other , nextOther};
            if (nextOther > last  ){
                cout << -1 << "\n";
                return  0;
            }
            nextOther++;
            if (nextOther == n + 1){
                other ++;
                nextOther = other + 2 ;
            }
        }
    }
    for (auto cur : ans ){
        cout << cur.first << " " << cur.second << "\n";
    }

    return 0;
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
int const MAXN = 1e5 + 9 ;
int n,m;
LL cost = 0 , w = 0;
vector<pair<int,int>> ans;
vector<pair <pair<int,int>,int> > v;
int nxt[MAXN];
priority_queue < pair <int,int > > pq;
int main (){
    ios_base :: sync_with_stdio(0);
    cin . tie (0) , cout . tie (0);
    cin >> n >> m ;
    int last = 1;
    int other = 1;

    ans.resize(m);
    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        v . emplace_back(make_pair(u,-b),i);
    }
    for (int i = 1 ;i <= n ;i++){
        pq.push ({-(i+2),i});
    }

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

    for (auto cur : v) {
        int  w = cur . first . first;
        int  b = cur . first . second ;
        int  i = cur . second ;
        //cout << w << " "<< b << " "<< i << endl;
        if ( b ) {
            ans [i] = {last,last + 1};
            last++;
        }else {
            int nextOther = abs (pq. top () . first) ;
            int other = abs (pq. top () . second) ;
            pq.pop();
            if ( nextOther> last  ){
                cout << -1 << "\n";
                return  0;
            }
            ans[i] = { other , nextOther};

            pq.push( {-(++nextOther),other});
        }
    }
    for (auto cur : ans ){
        cout << cur.first << " " << cur.second << "\n";
    }

    return 0;
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
int const MAXN = 1e5 + 9 ;
int n,m;
LL cost = 0 , w = 0;
vector<pair<int,int>> ans;
vector<pair <pair<int,int>,int> > v;
priority_queue < pair <int,int > > pq;
int main (){
    ios_base :: sync_with_stdio(0);
    cin . tie (0) , cout . tie (0);
    cin >> n >> m ;
    int last = 1 ;
    int other = 1 ;
    ans.resize(m);

    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        v . emplace_back(make_pair(u,-b),i);
    }

    for (int i = 1 ;i <= n ;i++){
        pq.push ({-(i+2),i});
    }

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

    for (auto cur : v) {
        int  b = cur . first . second ;
        int  i = cur . second ;
        if ( b ) {
            ans [i] = {last,last + 1};
            last++;
        }else {
            int nextOther = abs (pq. top () . first) ;
            int other = abs (pq. top () . second) ;
            pq.pop();
            if ( nextOther > last  ){
                cout << -1 << "\n";
                return  0;
            }
            ans[i] = { other , nextOther};
            pq.push( {-(++nextOther),other} );
        }
    }

    for (auto cur : ans )
        cout << cur.first << " " << cur.second << "\n";
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
vector<int> parent, sz;

void make_set(int v) {
    parent[v] = v;
    sz[v] = 0;
}

int find_set(int v) {
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_sets(int a, int b) {
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        if (sz[a] < sz[b])
            swap(a, b);
        parent[b] = a;
        if (sz[a] == sz[b])
            sz[a]++;
    }
}

struct Edge {
    int u, v;
    LL weight;
    Edge (){};
    Edge (int u,int v,LL weight):u(u),v(v),weight(weight){};
    bool operator<(Edge const& other) {
        return weight < other.weight;
    }
};
int n,m;
LL cost = 0 , w = 0;
vector<Edge> edges;
vector<Edge> ans;
vector < vector < pair <int , LL > > >  adj;
int main (){
    cin >> n >> m ;
    parent.resize(n+1);
    sz.resize(n+1);
    int last = 1;
    int other = 1;
    int nextOther = 3;
    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        if (b == 1){
            w += u;
            edges.push_back(  Edge (last,last+1,u));
            last++;
        }else {
             edges.push_back(  Edge (other,nextOther,u));
             nextOther++;
             if (nextOther == n+1){
                    other++;
                    nextOther = other + 2;
             }
        }
    }

     for (int i = 0; i < n; i++)
        make_set(i);
    ans = edges;
    sort(edges.begin(), edges.end());

    for (Edge e : edges) {
        //cout << e.u << " " << e.v << " " << e.weight <<endl;
        if (find_set(e.u) != find_set(e.v)) {
            cost += e.weight;
            union_sets(e.u, e.v);
        }
    }
    if (cost == w ){
        for (auto e : ans ){
            cout << e.u << " " << e.v << "\n";
        }
    }else cout << -1 << "\n";

    return 0;
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
int n,m;
LL cost = 0 , w = 0;
vector<pair<int,int>> ans;
vector<pair <pair<int,int>,int> > v;
int main (){
    ios_base :: sync_with_stdio(0);
    cin . tie (0) , cout . tie (0);
    cin >> n >> m ;
    int last = 1;
    int other = 1;
    int nextOther = 3;
    ans.resize(m);
    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        v . emplace_back(make_pair(u,b),i);
    }

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

    for (auto cur : v) {
        int  w = cur . first . first;
        int  b = cur . first . second ;
        int  i = cur . second ;
        //cout << w << " "<< b << " "<< i << endl;
        if ( b ) {
            ans [i] = {last,last + 1};
            last++;
        }else {
            ans[i] = { other , nextOther};
            if (nextOther > last + 1 ){
                cout << -1 << "\n";
                return  0;
            }
            nextOther++;
            if (nextOther == n + 1){
                other ++;
                nextOther = other + 2 ;
            }
        }
    }
    for (auto cur : ans ){
        cout << cur.first << " " << cur.second << "\n";
    }

    return 0;
}


#include <bits/stdc++.h>
#define LL long long int
using namespace std;
int n,m;
LL cost = 0 , w = 0;
vector<pair<int,int>> ans;
vector<pair <pair<int,int>,int> > v;
int main (){
    cin >> n >> m ;
    int last = 1;
    int other = 1;
    int nextOther = 3;
    ans.resize(m);
    for (int i = 0; i < m ;i++){
        LL u,b;
        cin >> u >> b;
        v . emplace_back(make_pair(u,b),i);
    }

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

    for (auto cur : v) {
        int  w = cur . first . first;
        int  b = cur . first . second ;
        int  i = cur . second ;
        cout << w << " "<< b << " "<< i << endl;
        if ( b ) {
            ans [i] = {last,last + 1};
            last++;
        }else {
            ans[i] = { other , nextOther};
            if (nextOther > last + 1 ){
                cout << -1 << "\n";
                return  0;
            }
            nextOther++;
            if (nextOther == n + 1){
                other ++;
                nextOther = other + 2 ;
            }
        }
    }
    for (auto cur : ans ){
        cout << cur.first << " " << cur.second << "\n";
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
#define mem(a, b) memset(a, b, sizeof(a))
#define INF 0X3f3f3f3f
const ll MAXN = 100000 + 7;
const ll MOD = 1e9 + 7;
//-------------------------------------------//
struct pop
{
    int v, p, i;
} pos[MAXN];
bool cmp1(pop x, pop y)
{
    if (x.v == y.v)
        return x.p > y.p;
    return x.v < y.v;
}
queue<pop> s;
map<int, pop> mp;
int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    int cnt = 0;
    for (int i = 1; i <= m; i++)
    {
        scanf("%d %d", &pos[i].v, &pos[i].p);
        pos[i].i = i;
        if (pos[i].p == 0)
            cnt++;
    }
    sort(pos + 1, pos + 1 + m, cmp1);
    int now = 1, flag = 0;
    for (int i = 1; i <= m; i++)
    {
        if (pos[i].p == 0)
        {
            if (s.empty())
            {
                flag = 1;
                break;
            }
            else
            {
                pop x = s.front();
                mp[pos[i].i].p = x.p;
                mp[pos[i].i].v = x.v;
                s.pop();
                cnt--;
            }
        }
        else
        {
            now++;
            if (now > n)
            {
                flag = 1;
                break;
            }
            mp[pos[i].i].p = 1;
            mp[pos[i].i].v = now;
            for (int j = 2; j < now; j++)
            {
                if (s.size() > cnt)
                {
                    break;
                }
                pop x;
                x.p = j;
                x.v = now;
                s.push(x);
            }
        }
    }
    if (flag == 1)
        printf("-1\n");
    else
    {
        for (int i = 1; i <= m; i++)
        {
            printf("%d %d\n", mp[i].p, mp[i].v);
        }
    }
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

int par[maxn];

int find_rep(int r) {
      if (r == par[r]) {
            return r;
      }
      return par[r] = find_rep(par[r]);
}

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <Edge> ans;
      for (int i = 0; i < alive.size(); i++) {
            int u = 1;
            int v = i + 2;
            int w = alive[i].first;
            int id = alive[i].second;
            ans.eb(u, v, w, 1, id);
      }
      int u = 2;
      while (u < n) {
            int v = u + 1;
            while (v <= n and dead.size()) {
                  int w = dead.front().first;
                  int id = dead.front().second; dead.pop_front();
                  ans.eb(u, v, w, 0, id);
                  v++;
            }
            u++;
      }
      if (dead.size()) {
            no();
      }
      iota(par, par + maxn, 0);
      sort(all(ans));
      for (Edge it : ans) {
            cerr << it.u << " " << it.v << " " << it.w << " " << it.t << " " << it.id << endl;
      }
      for (Edge it : ans) {
            int u = it.u;
            int v = it.v;
            int w = it.w;
            int t = it.t;
            int id = it.id;
            int p = find_rep(u);
            int q = find_rep(v);
            debug(u, v, p, q, t, id);
            if (p == q) {
                  if (t == 1) {
                        no();
                  }
                  continue;
            }
            if (t == 0) {
                  no();
            }
            par[q] = p;
      }
      pii graph[n + 1];
      for (Edge it : ans) {
            graph[it.id] = {it.u, it.v};
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <pii> graph(m + 1);
      vector <int> asign(n + 1);
      for (int i = 0; i < alive.size(); i++) {
            int u = i + 1;
            int v = u + 1;
            int w = alive[i].first;
            int id = alive[i].second;
            graph[id] = mk(u, v);
            debug(u, v, w);
            asign[v] = w;
      }
      int last = 1;
      multiset <pii> ms;
      for (auto it : dead) {
            ms.insert(it);
      }
      while (last < n and ms.size()) {
            int u = last;
            int v = u + 2;
            while (v <= n and ms.size()) {
                  int myw = asign[v];
                  auto lb = ms.lower_bound(mk(myw, -1));
                  if (lb == ms.end()) {
                        break;
                  }
                  int w = (*lb).ff;
                  int id = (*lb).ss;
                  graph[id] = mk(u, v);
                  ms.erase(lb);
                  v++;
            }
            last++;
      }
      if (ms.size()) {
            no();
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

int par[maxn];

int find_rep(int r) {
      if (r == par[r]) {
            return r;
      }
      return par[r] = find_rep(par[r]);
}

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <Edge> ans;
      for (int i = 0; i < alive.size(); i++) {
            int u = 1;
            int v = i + 2;
            int w = alive[i].first;
            int id = alive[i].second;
            ans.eb(u, v, w, 1, id);
      }
      int u = 2;
      while (u < n) {
            int v = u + 1;
            while (v <= n and dead.size()) {
                  int w = dead.front().first;
                  int id = dead.front().second; dead.pop_front();
                  ans.eb(u, v, w, 0, id);
                  v++;
            }
            u++;
      }
      if (dead.size()) {
            no();
      }
      iota(par, par + maxn, 0);
      sort(all(ans));
      for (Edge it : ans) {
            int u = it.u;
            int v = it.v;
            int w = it.w;
            int t = it.t;
            int id = it.id;
            int p = find_rep(u);
            int q = find_rep(v);
            debug(u, v, p, q, t, id);
            if (p == q) {
                  if (t == 1) {
                        no();
                  }
                  continue;
            }
            if (t == 0) {
                  no();
            }
            par[q] = p;
      }
      pii graph[n + 1];
      for (Edge it : ans) {
            graph[it.id] = {it.u, it.v};
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <pii> graph(m + 1);
      vector <int> asign(n + 1);
      for (int i = 0; i < alive.size(); i++) {
            int u = i + 1;
            int v = u + 1;
            int w = alive[i].first;
            int id = alive[i].second;
            graph[id] = mk(u, v);
            debug(u, v, w);
            asign[v] = w;
      }
      int last = 1;
      multiset <pii> ms;
      for (auto it : dead) {
            ms.insert(it);
      }
      while (last < n and ms.size()) {
            int u = last;
            int v = u + 2;
            while (v <= n and ms.size()) {
                  int myw = asign[v];
                  auto lb = ms.lower_bound(mk(myw, -1));
                  if (lb == ms.end()) {
                        break;
                  }
                  int w = (*lb).ff;
                  int id = (*lb).ss;
                  graph[id] = mk(u, v);
                  ms.erase(lb);
                  v++;
            }
            last++;
      }
      if (ms.size()) {
            no();
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

int par[maxn];

int find_rep(int r) {
      if (r == par[r]) {
            return r;
      }
      return par[r] = find_rep(par[r]);
}

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <Edge> ans;
      for (int i = 0; i < alive.size(); i++) {
            int u = 1;
            int v = i + 2;
            int w = alive[i].first;
            int id = alive[i].second;
            ans.eb(u, v, w, 1, id);
      }
      int last = 2;
      int add = 1;
      while (last < n and dead.size()) {
            int u = last;
            int v = u + add;
            while (v <= n and dead.size()) {
                  int w = dead.front().first;
                  int id = dead.front().second; dead.pop_front();
                  ans.eb(u, v, w, 0, id);
                  u++;
                  v += add;
            }
            last++;
            add++;
      }
      if (dead.size()) {
            no();
      }
//      for (Edge it : ans) {
//            cerr << it.u << " " << it.v << " " << it.w << " " << it.t << " " << it.id << endl;
//      }
      iota(par, par + maxn, 0);
      sort(all(ans));
      for (Edge it : ans) {
            int u = it.u;
            int v = it.v;
            int w = it.w;
            int t = it.t;
            int id = it.id;
            int p = find_rep(u);
            int q = find_rep(v);
            debug(u, v, p, q, t, id);
            if (p == q) {
                  if (t == 1) {
                        no();
                  }
                  continue;
            }
            if (t == 0) {
                  no();
            }
            par[q] = p;
      }
      pii graph[m + 1];
      for (Edge it : ans) {
            graph[it.id] = {it.u, it.v};
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <Edge> ans;
      vector <int> asign(n + 1);
      for (int i = 0; i < alive.size(); i++) {
            int u = i + 1;
            int v = u + 1;
            int w = alive[i].first;
            int id = alive[i].second;
            ans.eb(u, v, w, 1, id);
            debug(u, v, w);
            asign[v] = w;
      }
      int last = 1;
      multiset <pii> ms;
      for (auto it : dead) {
            ms.insert(it);
      }
      while (last < n and ms.size()) {
            int u = last;
            int v = u + 2;
            while (v <= n and ms.size()) {
                  int myw = asign[v];
                  auto lb = ms.lower_bound(mk(myw, -1));
                  if (lb == ms.end()) {
                        break;
                  }
                  int w = (*lb).ff;
                  int id = (*lb).ss;
                  ans.eb(u, v, w, 0, id);
                  ms.erase(lb);
                  v++;
            }
            last++;
      }
      if (ms.size()) {
            no();
      }
      pii graph[m + 1];
      for (Edge it : ans) {
            graph[it.id] = {it.u, it.v};
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

int par[maxn];

int find_rep(int r) {
      if (r == par[r]) {
            return r;
      }
      return par[r] = find_rep(par[r]);
}

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <Edge> ans;
      vector <int> asign(n + 1);
      for (int i = 0; i < alive.size(); i++) {
            int u = i + 1;
            int v = u + 1;
            int w = alive[i].first;
            int id = alive[i].second;
            ans.eb(u, v, w, 1, id);
            debug(u, v, w);
            asign[v] = w;
      }
      int last = 1;
      multiset <pii> ms;
      for (auto it : dead) {
            ms.insert(it);
      }
      while (last < n and ms.size()) {
            int u = last;
            int v = u + 2;
            while (v <= n and ms.size()) {
                  int myw = asign[v];
                  auto lb = ms.lower_bound(mk(myw, -1));
                  if (lb == ms.end()) {
                        break;
                  }
                  int w = (*lb).ff;
                  int id = (*lb).ss;
                  ans.eb(u, v, w, 0, id);
                  ms.erase(lb);
                  v++;
            }
            last++;
      }
      if (ms.size()) {
            no();
      }
      pii graph[m + 1];
      for (Edge it : ans) {
            graph[it.id] = {it.u, it.v};
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}


#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#include "ext/rope"

using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;

//#pragma GCC optimize("O3")
//#pragma GCC optimize("unroll-loops")
//#pragma GCC target("avx,avx2,fma")

void trace(int x)                         { cerr << x; }
void trace(long x)                        { cerr << x; }
void trace(long long x)                   { cerr << x; }
void trace(unsigned x)                    { cerr << x; }
void trace(unsigned long x)               { cerr << x; }
void trace(unsigned long long x)          { cerr << x; }
void trace(float x)                       { cerr << x; }
void trace(double x)                      { cerr << x; }
void trace(long double x)                 { cerr << x; }
void trace(char x)                        { cerr << '\'' << x << '\''; }
void trace(const char *x)                 { cerr << '\"' << x << '\"'; }
void trace(const string &x)               { cerr << '\"' << x << '\"'; }
void trace(bool x)                        { cerr << (x ? "true" : "false"); }

template <typename A, typename B>                         void trace(const pair <A, B> &x)         { cerr << '{'; trace(x.first); cerr << ','; trace(x.second); cerr << '}'; }
template <typename A, typename B, typename C>             void trace(const tuple <A, B, C> &x)     { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << '}'; }
template <typename A, typename B, typename C, typename D> void trace(const tuple <A, B, C, D> &x)  { cerr << '{'; trace(get <0> (x)); cerr << ','; trace(get <1> (x)); cerr << ','; trace(get <2> (x)); cerr << ','; trace(get <3> (x)); cerr << '}'; }
template <typename T>                                     void trace(const T &x)                   { int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), trace(i); cerr << "}"; }
template <size_t N>                                       void trace(bitset <N> v)                 { cerr << '{'; for (size_t i = 0; i < N; i++) cerr << static_cast <char> ('0' + v[i]); cerr << '}'; }
void _print()                                                                                { cerr << "]\n"; }
template <typename T, typename... V>                      void _print(T t, V... v)                 { trace(t); if (sizeof...(v)) cerr << ", "; _print(v...); }

#ifndef ONLINE_JUDGE
      #define debug(x...) cerr << "[" << #x << "] = ["; _print(x)
#else
      #define debug(x...)
#endif

template <typename T> using ordered_set                = tree <T, null_type, less <T>, rb_tree_tag, tree_order_statistics_node_update>;
template <typename T1, typename T2> using ordered_map  = tree <T1, T2, less <T1>, rb_tree_tag, tree_order_statistics_node_update>;

template <class T> bool MIN(T &a, T b)                 { return a > b ? (a = b, true) : false; }
template <class T> bool MAX(T &a, T b)                 { return a < b ? (a = b, true) : false; }

template <class T> T binaryExpo(T a, T p)              { if (p == 0) { return 1LL; } if (p == 1) { return a; } if (p & 1) { return a * binaryExpo(a, p - 1); } T ret = binaryExpo(a, p / 2); return ret * ret; }
template <class T> T bigMod(T a, T p, T m)             { if (p == 0) { return 1LL % m; } if (p == 1) { return a % m; } if (p & 1) { return (a % m * bigMod(a, p - 1, m)) % m; } T ret = bigMod(a, p / 2, m) % m; return (ret * ret) % m; }
template <class T> T modInv(T a, T m)                  { return bigMod(a, m - 2, m); }

template <typename T> string num_str(T num)            { stringstream ss; ss << num; return ss.str(); }
long long str_num(string s)                            { long long num; istringstream iss(s); iss >> num; return num; }

inline long long ON(long long mask, int pos)           { return mask |= (1LL << pos); }
inline long long OFF(long long mask, int pos)          { return mask &= ~(1LL << pos); }
inline long long TOGGLE(long long mask, int pos)       { return mask ^= (1LL << pos); }
inline bool CHECK(long long mask, int pos)             { return (bool)(mask >> pos & 1LL); }

inline int ONE(long long mask)                         { return __builtin_popcountll(mask); }
inline int LZERO(long long mask)                       { return 31 - __builtin_clzll(mask); };
inline int TZERO(long long mask)                       { return __builtin_ctzll(mask); };

//int dr[] = {+1, -1, +0, +0};                         // 4 Direction - DOWN, UP, RIGHT, LEFT
//int dc[] = {+0, +0, +1, -1};
int dr[] = {+0, +0, +1, -1, +1, +1, -1, -1};       // 8 Direction - RIGHT, LEFT, DOWN, UP, RIGHT-DOWN, LEFT-DOWN, UP-RIGHT, UP-LEFT
int dc[] = {+1, -1, +0, +0, +1, -1, +1, -1};
//int dr[] = {-1, +1, -2, -2, -1, +1, +2, +2};       // knight Moves
//int dc[] = {-2, -2, -1, +1, +2, +2, +1, -1};

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

#define ll              long long int
#define ull             unsigned long long int
#define endl            '\n'
#define pii             pair <int, int>
#define pll             pair <ll, ll>
#define mk              make_pair
#define ff              first
#define ss              second
#define all(a)          (a).begin(), (a).end()
#define rall(a)         (a).rbegin(), (a).rend()
#define eb              emplace_back
#define pb              push_back
#define pf              push_front
#define allUpper(a)     transform(all(a), a.begin(), :: toupper)
#define allLower(a)     transform(all(a), a.begin(), :: tolower)
#define LINE            cerr << __LINE__ << " ";
#define memo(a, b)      memset(a, b, sizeof a)
#define ook             order_of_key
#define fbo             find_by_order

#define int             long long int

static const int maxn = 2e5 + 5;
static const int logn = 19;
static const long long MOD = 1e9 + 7;
static const long long INF = 1e18;

struct Edge {
      int u, v, w, t, id;
      Edge(int u = 0, int v = 0, int w = 0, int t = 0, int id = 0)
            : u(u), v(v), w(w), t(t), id(id) {}

      bool operator < (const Edge &other) const {
            if (w == other.w) {
                  return t > other.t;
            }
            return w < other.w;
      }
};

int par[maxn];

int find_rep(int r) {
      if (r == par[r]) {
            return r;
      }
      return par[r] = find_rep(par[r]);
}

void no() {
      cout << -1 << endl;
      exit(0);
}

signed main()
{
      ios_base::sync_with_stdio(false);
      cin.tie(nullptr);
      cout.precision(12);

      #ifndef ONLINE_JUDGE
          freopen("in.txt", "r", stdin);
      #endif // ONLINE_JUDGE

      int n, m;
      cin >> n >> m;
      deque <pii> alive;
      deque <pii> dead;
      for (int e = 1; e <= m; e++) {
            int w, t;
            cin >> w >> t;
            if (t == 1) {
                  alive.emplace_back(w, e);
            }
            else {
                  dead.emplace_back(w, e);
            }
      }
      sort(all(alive));
      sort(all(dead));
      vector <Edge> ans;
      for (int i = 0; i < alive.size(); i++) {
            int u = 1;
            int v = i + 2;
            int w = alive[i].first;
            int id = alive[i].second;
            ans.eb(u, v, w, 1, id);
      }
      int u = 2;
      while (u < n and dead.size()) {
            int v = u + 1;
            while (v <= n and dead.size()) {
                  int w = dead.front().first;
                  int id = dead.front().second; dead.pop_front();
                  ans.eb(u, v, w, 0, id);
                  v++;
            }
            u++;
      }
      if (dead.size()) {
            no();
      }
      iota(par, par + maxn, 0);
      sort(all(ans));
      for (Edge it : ans) {
            int u = it.u;
            int v = it.v;
            int w = it.w;
            int t = it.t;
            int id = it.id;
            int p = find_rep(u);
            int q = find_rep(v);
            debug(u, v, p, q, t, id);
            if (p == q) {
                  if (t == 1) {
                        no();
                  }
                  continue;
            }
            if (t == 0) {
                  no();
            }
            par[q] = p;
      }
      pii graph[m + 1];
      for (Edge it : ans) {
            graph[it.id] = {it.u, it.v};
      }
      for (int i = 1; i <= m; i++) {
            cout << graph[i].first << " " << graph[i].second << endl;
      }

      #ifndef ONLINE_JUDGE
            cerr << endl << "Time : " << 1.0 * clock() / CLOCKS_PER_SEC << " s." << endl;
      #endif // ONLINE_JUDGE

      return 0;
}