#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <utility>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <queue>
#include <deque>
#include <stack>
#include <fstream>
#include <cmath>
#include <random>
#include <complex>
#include <functional>

#define ll int64_t
#define Rep(i, n) for (ll i = 0; i < n; i++)
using namespace std;
typedef vector<ll> vec;
typedef vector<vec> mat;

const ll inf = 1LL << 60;

template<class T> inline void chmin(T& a, T b) {
    if (a > b) {
        a = b;
    }
}
template<class T> inline void chmax(T& a, T b) {
    if (a < b) {
        a = b;
    }
}

typedef pair<ll, ll> P;
vec d;
struct edge {
    ll from, to, cost, id, dir;
};
vector<vector<edge>> graph;

void dijkstra (ll s, ll V) {
    priority_queue<P, vector<P>, greater<P>> que;
    d.assign(V, inf);
    d[s] = 0;
    que.push(P(0, s));

    while (!que.empty()) {
        P p = que.top(); que.pop();
        ll v = p.second;
        if (d[v] < p.first) continue;
        for (edge e : graph[v]) {
            if (d[e.to] > d[v] + e.cost) {
                d[e.to] = d[v] + e.cost;
                que.push(P(d[e.to], e.to));
            }
        }
    }
}

vec depth;
void dfs (ll v, ll from) {
    for (auto nv : graph[v]) {
        if (nv.to == from) continue;
        if (depth[nv.to] != -1) continue;
        depth[nv.to] = depth[v] + 1;
        dfs(nv.to, v);
    }
}

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

    ll N, M;
    cin >> N >> M;
    if (M%2 == 1) {
        cout << "-1\n";
        return 0;
    }
    graph.assign(N, vector<edge>());
    vector<edge> edges(M);
    Rep (i, M) {
        ll A, B;
        cin >> A >> B;
        A--; B--;
        graph[A].push_back({A, B, 1, i, 0});
        graph[B].push_back({B, A, 1, i, 0});
        edges[i] = {A, B, 1, i, 0};
    }

    depth.assign(N, -1);
    depth[0] = 0;
    dfs(0, -1);

    // Rep (i, N) {
    //     cout << depth[i] << " \n"[i==N-1];
    // }

    map<ll, vec> m;
    ll max_d = -1;
    Rep (i, N) {
        m[depth[i]].push_back(i);
        chmax(max_d, depth[i]);
    }

    for (ll a : m[max_d]) {
        for (auto e : graph[a]) {
            // if (abs(depth[e.from] - depth[e.to]) % 2 == 0) {
            //     cout << "-1\n";
            //     return 0;
            // }

            ll id = e.id;
            if (edges[id].from == a) {
                edges[id].dir = -1;
            } else {
                edges[id].dir = 1;
            }
        }
    }

    for (ll i = max_d-1; i >= 0; i--) {
        for (ll a : m[i]) {
            vec yet;
            ll cnt = 0;
            for (auto e : graph[a]) {
                // if (abs(depth[e.from] - depth[e.to]) % 2 == 0) {
                //     cout << "-1\n";
                //     return 0;
                // }
                ll id = e.id;
                if (edges[id].from == a and edges[id].dir == 1 or edges[id].to == a and edges[id].dir == -1) {
                    cnt++;
                }
                if (edges[id].dir == 0) {
                    yet.push_back(id);
                }
            }

            for (ll id : yet) {
                if (cnt % 2 == 1) {
                    if (edges[id].from == a) {
                        edges[id].dir = 1;
                    } else {
                        edges[id].dir = -1;
                    }
                    cnt++;
                } else {
                    if (edges[id].from == a) {
                        edges[id].dir = -1;
                    } else {
                        edges[id].dir = 1;
                    }
                }
            }
        }
    }

    for (auto e : edges) {
        if (e.dir == 1) {
            cout << e.from+1 << " " << e.to+1 << "\n";
        } else {
            cout << e.to+1 << " " << e.from+1 << "\n";
        }
    }
}

Measured memory_bytes: 33408