use std::io::*;
use std::str::FromStr;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

type Weight = i32;
#[allow(dead_code)]
#[derive(Clone, Debug, Eq, PartialEq)]
struct Edge {
    index: usize,
    src: usize,
    dest: usize,
    weight: Weight,
}
#[allow(dead_code)]
impl Edge {
    fn new(index: usize, src: usize, dest: usize, weight: Weight) -> Edge {
        Edge {
            index: index,
            src: src,
            dest: dest,
            weight: weight,
        }
    }
}
impl std::cmp::Ord for Edge {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        (self.weight, self.src, self.dest).cmp(&(other.weight, other.src, other.dest))
    }
}
impl std::cmp::PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
type Edges = Vec<Edge>;
type Graph = Vec<Edges>;
#[allow(dead_code)]
fn graph_new(n: usize) -> Graph {
    vec![vec![]; n]
}
#[allow(dead_code)]
fn add_bi_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    graph[dest].push(Edge::new(*index, dest, src, weight));
    *index += 1;
}
#[allow(dead_code)]
fn add_uni_edge(graph: &mut Graph, index: &mut usize, src: usize, dest: usize, weight: Weight) {
    graph[src].push(Edge::new(*index, src, dest, weight));
    *index += 1;
}

fn dfs(g: &Graph, from: usize, parent: usize, parents: &mut Vec<usize>, orders: &mut Vec<usize>) {
    let n = g.len();
    if parents[from] != n {
        return;
    }
    parents[from] = parent;
    orders.push(from);
    for e in g[from].iter() {
        if e.dest == parent {
            continue;
        }
        dfs(g, e.dest, from, parents, orders);
    }
}

fn main() {
    let n = read::<usize>();
    let m = read::<usize>();
    let mut g = graph_new(n);
    let mut index = 0;
    for _i in 0..m {
        let a = read::<usize>() - 1;
        let b = read::<usize>() - 1;
        add_bi_edge(&mut g, &mut index, a, b, 1);
    }
    let mut parents = vec![n; n];
    let mut orders = vec![];
    dfs(&g, 0, 0, &mut parents, &mut orders);
    orders.reverse();
    let mut used = vec![false; m];
    let mut anss = vec![];
    for &from in orders.iter() {
        let mut parent_index = m;
        let mut cnt = 0;
        for e in g[from].iter() {
            if used[e.index] {
                continue;
            }
            if e.dest == parents[from] {
                parent_index = e.index;
                continue;
            }
            anss.push((e.src, e.dest));
            cnt += 1;
            used[e.index] = true;
        }
        if cnt % 2 == 1 {
            if from == 0 {
                anss.clear();
                break;
            }
            used[parent_index] = true;
            anss.push((from, parents[from]));
        }
    }
    if anss.len() != m {
        println!("-1");
    } else {
        for &(a, b) in anss.iter() {
            println!("{} {}", a + 1, b + 1);
        }
    }
}


Measured memory_bytes: 34172