#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define rrep(i, n) for (int i = (int)(n - 1); i >= 0; i--)
#define all(x) (x).begin(), (x).end()
#define sz(x) int(x.size())
#define get_unique(x) x.erase(unique(all(x)), x.end());
typedef long long ll;
typedef complex<double> Complex;
const int INF = 1e9;
const ll MOD = 1e9 + 7;
const ll LINF = 1e18;
template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T& a, const T& b) {
    if (b < a) {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
vector<T> make_vec(size_t a) {
    return vector<T>(a);
}
template <class T, class... Ts>
auto make_vec(size_t a, Ts... ts) {
    return vector<decltype(make_vec<T>(ts...))>(a, make_vec<T>(ts...));
}
template <typename T>
ostream& operator<<(ostream& os, vector<T> v) {
    for (int i = 0; i < sz(v); i++) {
        os << v[i];
        if (i < sz(v) - 1) os << " ";
    }
    return os;
}
struct HeavyLightComposition {
    int n;
    vector<vector<int>> g;
    vector<int> in, out, nx, sub, par, dep, inv, type;
    HeavyLightComposition(vector<vector<int>> g, int root = 0)
        : n(g.size()),
          g(g),
          in(n, -1),
          out(n, -1),
          nx(n),
          sub(n, 1),
          par(n, -1) {
        build(root);
    }
    void add_edge(int u, int v) {
        g[u].push_back(v);
        g[v].push_back(u);
    }
    void build(int root = 0) {
        int k = 0;
        dfs1(root);
        nx[root] = root;
        dfs2(root, k);
    }
    void dfs1(int now) {
        for (int& nxt : g[now])
            if (nxt == par[now]) swap(nxt, g[now].back());
        if (~par[now]) g[now].pop_back();

        for (int& nxt : g[now]) {
            par[nxt] = now;
            dfs1(nxt);
            sub[now] += sub[nxt];
            if (sub[nxt] > sub[g[now][0]]) swap(nxt, g[now][0]);
        }
    }
    void dfs2(int now, int& k) {
        in[now] = k++;
        for (int nxt : g[now]) {
            if (nxt == par[now]) continue;
            nx[nxt] = (nxt == g[now][0] ? nx[now] : nxt);
            dfs2(nxt, k);
        }
        out[now] = k;
    }
    template <typename F>
    void for_each_vertex(int u, int v, const F& f) {
        while (1) {
            if (in[u] > in[v]) swap(u, v);
            f(max(in[nx[v]], in[u]), in[v] + 1);
            if (nx[u] != nx[v])
                v = par[nx[v]];
            else
                break;
        }
    }
    template <typename F>
    void for_each_edge(int u, int v, const F& f) {
        while (1) {
            if (in[u] > in[v]) swap(u, v);
            if (nx[u] != nx[v]) {
                f(in[nx[v]], in[v] + 1);
                v = par[nx[v]];
            } else {
                if (u != v) f(in[u] + 1, in[v] + 1);
                break;
            }
        }
    }
};
template <typename T, typename E>
struct LazySegmentTree {
    using F = function<T(T, T)>;
    using G = function<T(T, E)>;
    using H = function<E(E, E)>;
    int sn, hei;
    F f;
    G g;
    H h;
    T ti;
    E ei;
    vector<T> node;
    vector<E> lazy;
    LazySegmentTree(const vector<T>& v, F f, G g, H h, T ti, E ei)
        : f(f), g(g), h(h), ti(ti), ei(ei) {
        int n = v.size();
        sn = 1, hei = 0;
        while (sn < n) {
            sn <<= 1;
            hei++;
        }
        node.assign(2 * sn, ti);
        lazy.assign(2 * sn, ei);
        for (int i = 0; i < n; i++) {
            node[sn + i] = v[i];
        }
        for (int i = sn - 1; i > 0; i--) {
            node[i] = f(node[(i << 1) | 0], node[(i << 1) | 1]);
        }
    }
    inline T reflect(int k) {
        return lazy[k] == ei ? node[k] : g(node[k], lazy[k]);
    }
    inline void propagate(int k) {
        if (lazy[k] == ei) return;
        lazy[(k << 1) | 0] = h(lazy[(k << 1) | 0], lazy[k]);
        lazy[(k << 1) | 1] = h(lazy[(k << 1) | 1], lazy[k]);
        node[k] = reflect(k);
        lazy[k] = ei;
    }
    inline void thrust(int k) {
        for (int i = hei; i > 0; i--) {
            propagate(k >> i);
        }
    }
    inline void recalc(int k) {
        while (k >>= 1) {
            node[k] = f(reflect((k << 1) | 0), reflect((k << 1) | 1));
        }
    }
    void update(int a, int b, E x) {
        if (a >= b) return;
        thrust(a += sn);
        thrust(b += sn - 1);
        for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
            if (l & 1) {
                lazy[l] = h(lazy[l], x);
                l++;
            }
            if (r & 1) {
                r--;
                lazy[r] = h(lazy[r], x);
            }
        }
        recalc(a);
        recalc(b);
    }
    void set_val(int a, T x) {
        thrust(a += sn);
        node[a] = x;
        lazy[a] = ei;
        recalc(a);
    }
    T query(int a, int b) {
        if (a >= b) return ti;
        thrust(a += sn);
        thrust(b += sn - 1);
        T vl = ti, vr = ti;
        for (int l = a, r = b + 1; l < r; l >>= 1, r >>= 1) {
            if (l & 1) {
                vl = f(vl, reflect(l));
                l++;
            }
            if (r & 1) {
                r--;
                vr = f(reflect(r), vr);
            }
        }
        return f(vl, vr);
    }
};
int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> G(n);
    vector<int> cnt(n);
    vector<pair<int, int>> edges(m);
    map<pair<int, int>, int> id;
    rep(i, m) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        cnt[a]++;
        edges[i] = {a, b};
        id[{a, b}] = id[{b, a}] = i;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    if (m & 1) {
        cout << -1 << endl;
        return 0;
    }

    vector<int> odd;
    rep(i, n) if (cnt[i] & 1) odd.push_back(i);

    queue<int> q;
    q.push(0);
    vector<bool> d(n);
    d[0] = 1;
    vector<vector<int>> GG(n);
    while (sz(q)) {
        int now = q.front();
        q.pop();
        for (int nxt : G[now]) {
            if (d[nxt]) continue;
            d[nxt] = 1;
            q.push(nxt);
            GG[now].push_back(nxt);
            GG[nxt].push_back(now);
        }
    }

    G = GG;
    HeavyLightComposition hld(G);

    using P = pair<ll, ll>;
    auto f = [](P a, P b) { return P(a.first + b.first, a.second + b.second); };
    auto g = [](P a, ll b) { return P(a.first + b * a.second, a.second); };
    auto h = [](ll a, ll b) { return a + b; };
    LazySegmentTree<P, ll> segt(vector<P>(n, P(0, 1)), f, g, h, P(0, 0), 0);

    for (int i = 0; i < sz(odd); i += 2) {
        int l = odd[i], r = odd[i + 1];
        hld.for_each_edge(l, r, [&](int l, int r) { segt.update(l, r, 1); });
    }

    vector<bool> swaped(m);
    vector<bool> checked(m);
    q.push(0);
    checked[0] = 1;
    while (sz(q)) {
        int now = q.front();
        q.pop();
        for (int nxt : G[now]) {
            if (checked[nxt]) continue;
            checked[nxt] = 1;
            q.push(nxt);
            ll sum = 0;
            hld.for_each_edge(
                now, nxt, [&](int l, int r) { sum += segt.query(l, r).first; });
            if (sum & 1) swaped[id[{now, nxt}]] = 1;
        }
    }

    rep(i, m) {
        if (swaped[i]) {
            cout << edges[i].second + 1 << " " << edges[i].first + 1 << endl;
        } else {
            cout << edges[i].first + 1 << " " << edges[i].second + 1 << endl;
        }
    }
}

Measured memory_bytes: 45144