#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
const ll INF = (ll)1000000007 * 1000000007;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef long double ld;
typedef complex<ld> Point;
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ll, ll> LP;

const int MAX_N = 100000;
const int MAX_E = 100000;
int n,m; //頂点数,辺数
struct edge{ll to, cost; };
struct edge_for_que{
    ll cost, to ,from; 

    bool operator > ( const edge_for_que& right) const{
    return this -> cost > right.cost;
    }
};
vector<edge> G[MAX_N]; //グラフ
bool used[MAX_N];
vector<edge> mintree[MAX_N]; //最小全域木の辺集合

int prim(){
    ll res = 0;
    priority_queue< edge_for_que, vector<edge_for_que>, greater<edge_for_que> > que;
    edge_for_que p = {0,0,0};
    que.push(p);
    while(!que.empty()){
        edge_for_que p = que.top(); que.pop();
        if(used[p.to]) continue;
        used[p.to] = true;
        res+=p.cost;
        edge e = {p.to, p.cost};
        if(p.to != 0){
            mintree[p.from].push_back(e);
        }
        rep(i,G[p.to].size()){
            edge_for_que q = {G[p.to][i].cost,G[p.to][i].to,p.to};
            que.push(q);
        }
    }
    return res;
}

vector<int> parent,ans,children;
vector<bool> visited,used_edge;
queue<int> que;

void solve(){
    cin >> n >> m;
    parent.resize(n,-1);
    ans.resize(n,0);
    visited.resize(n,false);
    used_edge.resize(m,false);
    children.resize(n,0);
    if (m%2!=0) {
        cout << -1 << endl;
        return;
    }
    rep(i,m){
        int a,b;
        cin >> a >> b;
        G[a-1].push_back(edge{b-1,i});
        G[b-1].push_back(edge{a-1,i});
    }
    prim();
    cout << "" << endl;
    rep(i,n){
        children[i]=mintree[i].size();
        if(mintree[i].size()!=0) {
            rep(k,mintree[i].size()){
                //cout << i << " " << mintree[i][k].to << endl;
                parent[mintree[i][k].to]=i;
            }
        }
        else {
            que.push(i);
            //cout << i << endl;
        }
    }
    // rep(i,n){
    //     cout << i+1 <<" " << parent[i]+1 << endl;
    // }
    while(!que.empty()){
        int a=que.front();
        que.pop();
        if (visited[a]) continue;
        visited[a]=true;
        if (a==0) continue;
        //cout << a+1 << endl;
        int l;
        rep(i,G[a].size()){
            //cout << G[a][i].cost << endl;
            int b = G[a][i].to;
            if (b==parent[a]) {
                l=G[a][i].cost;
                continue;
            }
            if (used_edge[G[a][i].cost]) continue;
            ans[a]+=1;
            cout << a+1 << " " << b+1 << endl;;
            used_edge[G[a][i].cost]=true;
        }
        //cout << "parent" << " " << a+1 << " " << l+1 << endl;
    

        if (ans[a]%2) {
            ans[a]+=1;
            cout << a+1 << " " << parent[a]+1 << endl;
            used_edge[l]=true;
        }else{
            ans[parent[a]]+=1;
            cout << parent[a]+1 << " " << a+1 << endl;
            used_edge[l]=true;
        }
        children[parent[a]]-=1;
        if (children[parent[a]]==0) que.push(parent[a]);

    }



}

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

Measured memory_bytes: 18160