#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll

#define REP(i,n) for(int i=0;i<n;++i)
#define ALL(name) name.begin(),name.end()
#define SORT(name) sort(name.begin(), name.end())
#define ZERO(p) memset(p, 0, sizeof(p))
#define MINUS(p) memset(p, -1, sizeof(p))
#if 1
#  define DBG(fmt, ...) printf(fmt, ##__VA_ARGS__)
#else
#  define DBG(fmt, ...)
#endif

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const double DINF = std::numeric_limits<double>::infinity();
const int MOD = 1000000007;
#define MAX_N 100010
#define MAX_M 100010

int N, M;
vector<int> A, B;

int edge_out[MAX_N];        // ノード i の出次数
int depth[MAX_N];           // 木におけるノード i の深さ
vector<int> graph[MAX_N];   // 隣接リスト
map< pair<int, int>, int> edge_to_id;
pair<int, int> id_to_edge[MAX_M];
bool is_node_used[MAX_N];   // ノード i は使用済みか(全域木構成に利用)
bool is_edge_used[MAX_M];   // 辺 i は使用済みか
bool is_tree_edge[MAX_M];   // 全域木に使われている辺なら true

vector< pair<int, int> > ans;

// 辺 id の取得
static inline int GetEdgeId(int n1, int n2) { return edge_to_id[make_pair(min(n1, n2), max(n1, n2))]; }

// 全域木の構成
void MakeTree(int node, int d) {
    is_node_used[node] = true;
    depth[node] = d;
    for(auto& n : graph[node]) {
        int e_id = GetEdgeId(node, n);
        if(!is_node_used[n]) {
            is_tree_edge[e_id] = true;
            MakeTree(n, d + 1);
        }
    }
}

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

    cin >> N >> M;
    A.resize(M); B.resize(M);
    int edge_cnt = 0;
    REP(i, M) {
        int a, b;
        cin >> a >> b;
        a--; b--;
        if(a > b) { swap(a, b); }
        graph[a].push_back(b);
        graph[b].push_back(a);
        edge_to_id[make_pair(a, b)] = edge_cnt;
        id_to_edge[edge_cnt] = make_pair(a, b);
        edge_cnt++;
    }

    if(M % 2 != 0) {
        printf("-1\n");
        return 0;
    }

    // 全域木の構成
    MakeTree(0, 0);

    // 全域木の構成に使われていない辺を適当に向き付ける
    REP(e, edge_cnt) {
        if(!is_tree_edge[e]) {
            auto tmp_edge = id_to_edge[e];
            ans.push_back(tmp_edge);
            edge_out[tmp_edge.first]++;
            is_edge_used[e] = true;
        }
    }

    // 全域木を深い頂点から見ていき、出次数を調整
    vector< pair<int, int> > nodes; // first: 深さ second: id
    REP(i, N) {
        nodes.push_back(make_pair(depth[i], i));
    }
    sort(nodes.begin(), nodes.end(), greater< pair<int, int> > ());

    for(auto& node_info : nodes) {
        if(node_info.second == 0) { break; }

        int node_id = node_info.second;
        // 全域木に使われていない辺を探す
        int parent = -1;
        for(auto& cand : graph[node_id]) {
            int e_id = GetEdgeId(node_id, cand);
            if(!is_edge_used[e_id] && is_tree_edge[e_id]) {
                parent = cand;
                break;
            }
        }
        assert(parent >= 0);

        if(edge_out[node_id] % 2 == 0) {
            // 偶数なら、受け入れる方向に辺を張る
            ans.push_back(make_pair(parent, node_id));
            edge_out[parent]++;
        }
        else {
            // 奇数なら、出す方向に辺を張る
            ans.push_back(make_pair(node_id, parent));
            edge_out[node_id]++;
        }
        is_edge_used[GetEdgeId(parent, node_id)] = true;
    }

    for(auto& e_ans : ans) {
        printf("%lld %lld\n", e_ans.first + 1, e_ans.second + 1);
    }


    return 0;
}


Measured memory_bytes: 30960