extern crate core;

use std::fmt;
use std::cmp::{Ordering, min, max};
use std::fmt::{Display, Error, Formatter};
use std::ops::{Index, IndexMut, Add, AddAssign, Sub, SubAssign, Mul, MulAssign};
use std::collections::VecDeque;
use std::f32::MAX;

fn show<T: Display>(vec: &Vec<T>) {
    if vec.is_empty() {
        println!("[]");
    }else {
        print!("[{}", vec[0]);
        for i in 1 .. vec.len() {
            print!(", {}", vec[i]);
        }
        println!("]");
    }
}
macro_rules! read_line{
    () => {{
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).ok();
        line
    }};
    (delimiter: ' ') => {
        read_line!().split_whitespace().map(|x|x.to_string()).collect::<Vec<_>>()
    };
    (delimiter: $p:expr) => {
        read_line!().split($p).map(|x|x.to_string()).collect::<Vec<_>>()
    };
    (' ') => {
        read_line!(delimiter: ' ')
    };
    ($delimiter:expr) => {
        read_line!(delimiter: $delimiter)
    };
    (' '; $ty:ty) => {
        read_line!().split_whitespace().map(|x|x.parse::<$ty>().ok().unwrap()).collect::<Vec<$ty>>()
    };
    ($delimiter:expr; $ty:ty) => {
        read_line!($delimiter).into_iter().map(|x|x.parse::<$ty>().ok().unwrap()).collect::<Vec<$ty>>()
    };
}
macro_rules! let_all {
    ($($n:ident:$t:ty),*) => {
        let line = read_line!(delimiter: ' ');
        let mut iter = line.iter();
        $(let $n:$t = iter.next().unwrap().parse().ok().unwrap();)*
    };
}
struct UnionFind {
    size: usize, vec: Vec<i32>
}
impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind{size: size, vec: vec![-1; size]}
    }
    fn find(&mut self, a: usize) -> usize {
        if self.vec[a] < 0 {
            a
        }else {
            let ar = self.vec[a] as usize;
            let r = self.find(ar);
            self.vec[a] = r as i32;
            r
        }
    }
    fn same(&mut self, a: usize, b: usize) -> bool {
       self.find(a) == self.find(b)
    }
    fn merge(&mut self, new_root: usize, b: usize) {
        let ar = self.find(new_root);
        let br = self.find(b);
        if ar != br {
            self.vec[ar] += self.vec[br];
            self.vec[br] = ar as i32;
        }
    }
    fn reset(&mut self) {
        for i in 0 .. self.vec.len() {
            self.vec[i] = -1;
        }
    }
}
fn max_matching(nodes: &Vec<Vec<usize>>) -> Vec<(usize, usize)> {
    let sentinel = nodes.len();
    let mut matching = vec![sentinel;nodes.len()];
    let mut free = vec![sentinel; nodes.len()];
    let mut tree_id = vec![sentinel; nodes.len()];
    let mut merged_root = UnionFind::new(nodes.len() + 1);
    let mut depth = vec![sentinel; nodes.len()];
    let mut stack = Vec::<usize>::with_capacity(nodes.len());
    for _ in 0 .. nodes.len() {
        for i in 0 .. nodes.len() {
            if matching[i] == sentinel{
                stack.push(i);
                tree_id[i] = i;
                depth[i] = 0;
            }
        }
        while let Some(t) = stack.pop() {
            if depth[t] % 2 == 0 {
                for &n in &nodes[t] {
                    if matching[t] != n {
                        if tree_id[n] == sentinel {
                            tree_id[n] = tree_id[t];
                            depth[n] = depth[t] + 1;
                            free[n] = t;
                            stack.push(matching[n]);
                            tree_id[matching[n]] = tree_id[t];
                            depth[matching[n]] = depth[n] + 1;
                        } else if depth[n] % 2 == 0 {
                            if tree_id[n] == tree_id[t] {
                                let mut n_ancestor = merged_root.find(n);
                                let mut t_ancestor = merged_root.find(t);
                                while n_ancestor != t_ancestor {
                                    if depth[n_ancestor] < depth[t_ancestor] {
                                        t_ancestor = merged_root.find(free[matching[t_ancestor]]);
                                    } else {
                                        n_ancestor = merged_root.find(free[matching[n_ancestor]]);
                                    }
                                }
                                let lca = n_ancestor;
                                n_ancestor = merged_root.find(n);
                                t_ancestor = merged_root.find(t);
                                while n_ancestor != lca {
                                    let prev = free[matching[n_ancestor]];
                                    free[prev] = matching[n_ancestor];
                                    merged_root.merge(lca, n_ancestor);
                                    n_ancestor = merged_root.find(free[matching[n_ancestor]]);
                                }
                                while t_ancestor != lca {
                                    let prev = free[matching[t_ancestor]];
                                    free[prev] = matching[t_ancestor];
                                    merged_root.merge(lca, t_ancestor);
                                    t_ancestor = merged_root.find(free[matching[t_ancestor]])
                                }
                                free[n] = t;
                                free[t] = n;
                            } else {
                                let mut current = matching[t];
                                while current != sentinel {
                                    let next = matching[free[current]];
                                    matching[current] = free[current];
                                    matching[free[current]] = current;
                                    current = next;
                                }
                                current = matching[n];
                                while current != sentinel {
                                    let next = matching[free[current]];
                                    matching[current] = free[current];
                                    matching[free[current]] = current;
                                    current = next;
                                }
                                matching[n] = t;
                                matching[t] = n;
                                stack.clear();
                                break;
                            }
                        }
                    }
                }
            }
        }
        for i in 0 .. nodes.len() {
            free[i] = sentinel;
            tree_id[i] = sentinel;
            depth[i] = sentinel;
        }
        merged_root.reset();
    }
    let mut result = Vec::new();
    for i in 0 .. nodes.len() {
        if matching[i] != sentinel && matching[i] < i {
            result.push((matching[i], i));
        }
    }
    result
}
fn main() {
    let_all!(n: usize, m: usize);

    let mut planes = vec![vec![true; n]; n];
    for _ in 0 .. m {
        let_all!(a: usize, b: usize);
        planes[a - 1][b - 1] = false;
        planes[b - 1][a - 1] = false;
    }
    if n % 2 == 0 {
        let mut nodes = vec![Vec::new(); n];
        for i in 0..n {
            for j in 0..n {
                if i != j && planes[i][j] {
                    nodes[i].push(j);
                }
            }
        }
        let pairs = max_matching(&nodes);
        if pairs.len() * 2 == n {
            for (a, b) in pairs {
                planes[a][b] = false;
                planes[b][a] = false;
            }
            println!("{}", n * (n - 1) / 2 - m - n / 2);
            for i in 0 .. n {
                for j in i + 1 .. n {
                    if planes[i][j] {
                        println!("{} {}", i + 1, j + 1);
                    }
                }
            }
        }else {
            println!("-1");
        }
    }else {
        println!("{}", n * (n - 1) / 2 - m);
        for i in 0 .. n {
            for j in i + 1 .. n {
                if planes[i][j] {
                    println!("{} {}", i + 1, j + 1);
                }
            }
        }
    }
}


Measured memory_bytes: 5048