/*
Copyright 2012 Marek "p2004a" Rusinowski
Edmonds's matching algorithm O(mn)
*/
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int max_n = 10000;
vector<int> edges[max_n * 2], /* graph */
contains[max_n * 2]; /* for every pseudonode contains list of cycle nodes */
int n, m, num_cycles = 0, match[max_n * 2],
d[max_n * 2], /* distance from node to tree root, we care only if it's even */
f[max_n * 2], /* root of tree that contains node */
a[max_n * 2]; /* ancestor of node in tree, correct for nodes with odd dist */
bool act[max_n * 2]; /* determines if node is active */
long long time = 0, t[max_n * 2];
void build_alternating_tree(int father, int dist = 0, int v = -1) {
if (v == -1) v = father;
d[v] = dist;
f[v] = father;
for (int i = 0; i < (int)edges[v].size(); ++i) {
if (d[edges[v][i]] == -1 && match[edges[v][i]] != -1) {
d[edges[v][i]] = dist + 1;
f[edges[v][i]] = father;
a[edges[v][i]] = v;
build_alternating_tree(father, dist + 2, match[edges[v][i]]);
}
}
}
void build_alternating_forest() {
/* delete old forest */
fill(d, d + n + num_cycles, -1);
/* build new forest, we start building tree from unmatched vertex */
for (int i = 0; i < n + num_cycles; ++i) {
if (match[i] == -1) {
build_alternating_tree(i);
}
}
}
void add_neighbours_from_to(int u, int v) {
for (int i = 0; i < (int) edges[u].size(); ++i) {
if (act[edges[u][i]]) {
edges[edges[u][i]].push_back(v);
edges[v].push_back(edges[u][i]);
/* We must remember about this if because without it we would had to
rebuild whole M-alternating tree after finding cycle. */
if (a[edges[u][i]] == u) {
a[edges[u][i]] = v;
}
}
}
}
inline void cycle_build_helper(int &v, vector<int> &in) {
act[v] = false;
in.push_back(v);
act[match[v]] = false;
in.push_back(match[v]);
v = a[match[v]];
}
void lca_helper(int &v, bool &path_v_end, bool &v_hit, long long time_begin) {
if (!path_v_end) {
if (t[v] < time_begin) {
t[v] = time;
} else {
v_hit = true;
return;
}
if (match[v] != -1) {
v = a[match[v]];
} else {
path_v_end = true;
}
}
}
void contract_cycle(int v, int u) {
/* If we haven't much time we can implement finding cycle nodes as pushing
all nodes from u->root and v->root to two vectors and then pop_backs from them
until last elements exists and are equal. The computional complexity will
increase to about O(n^4) using this technique. */
int cycle_v = n + num_cycles++;
long long time_begin = ++time;
/* find lca */
int new_v = v, new_u = u, shift;
bool path_v_end = false, path_u_end = false, v_hit = false, u_hit = false;
while (!v_hit && !u_hit) {
lca_helper(new_v, path_v_end, v_hit, time_begin);
lca_helper(new_u, path_u_end, u_hit, time_begin);
++time;
}
shift = time - t[v_hit ? new_v : new_u] - 1;
/* align nodes to the same level in tree using shift computed with lca */
vector<int> p;
while(shift--) {
cycle_build_helper(v_hit ? v : u, v_hit ? contains[cycle_v] : p);
}
/* build rest of cycle */
while (v != u) {
cycle_build_helper(v, contains[cycle_v]);
cycle_build_helper(u, p);
}
contains[cycle_v].insert(contains[cycle_v].end(), p.rbegin(), p.rend());
act[v] = false;
contains[cycle_v].push_back(v);
/* add to created pseudonode edges from cycle neighbours */
for (int j = 0; j < (int)contains[cycle_v].size(); ++j) {
add_neighbours_from_to(contains[cycle_v][j], cycle_v);
}
if (d[v] > 0) {
match[match[v]] = cycle_v;
match[cycle_v] = match[v];
} else {
match[cycle_v] = -1;
}
d[cycle_v] = d[v];
f[cycle_v] = f[v];
act[cycle_v] = true;
}
void reverse_match_to_root(int v, int old = -1) {
if (d[v] != 0) {
match[match[v]] = a[match[v]];
reverse_match_to_root(a[match[v]], match[v]);
}
match[v] = old;
}
inline bool check_node(int i) {
return act[i] && d[i] % 2 == 0;
}
bool find_path() {
for (int i = 0; i < n + num_cycles; ++i) {
if (check_node(i)) {
for (int j = 0; j < (int) edges[i].size(); ++j) {
if (check_node(edges[i][j])) {
if (f[i] == f[edges[i][j]]) {
contract_cycle(i, edges[i][j]);
return find_path();
} else {
reverse_match_to_root(i);
reverse_match_to_root(edges[i][j]);
match[i] = edges[i][j];
match[edges[i][j]] = i;
return true;
}
}
}
}
}
return false;
}
void expand_cycles() {
while (num_cycles--) {
int u, pos = 0, cycle_size = contains[num_cycles + n].size(),
cycle_v = num_cycles + n;
for (int i = 0; i < cycle_size; ++i) {
u = contains[cycle_v][i];
/* delete from cycle's neighbours pseudonode representing cycle */
for (int j = 0; j < (int) edges[u].size(); ++j) {
if (act[edges[u][j]]) {
if (edges[u][j] == match[cycle_v]) {
pos = i;
}
edges[edges[u][j]].pop_back();
}
}
}
for (int i = 0; i < cycle_size; ++i) {
act[contains[cycle_v][i]] = true;
}
u = contains[cycle_v][pos];
match[u] = match[cycle_v];
match[match[u]] = u;
/* build correct match on cycle */
for (int i = pos + 1; i < cycle_size + pos; i += 2) {
match[contains[cycle_v][i % cycle_size]] =
contains[cycle_v][(i + 1) % cycle_size];
match[contains[cycle_v][(i + 1) % cycle_size]] =
contains[cycle_v][i % cycle_size];
}
contains[cycle_v].clear();
edges[cycle_v].clear();
}
num_cycles = 0;
}
class degree_cmp {
public:
bool operator() (int b, int c) {
return edges[b].size() < edges[c].size();
}
} degree_comp;
/* creating match by trying to match nodes with smallest degree first */
void create_random_match() {
vector<int>nodes;
for (int i = 0; i < n; ++i) {
nodes.push_back(i);
}
sort(nodes.begin(), nodes.end(), degree_comp);
for (int i = 0; i < n; ++i) {
if (match[nodes[i]] == -1) {
int min_degree = 1000000, v = -1;
for (int j = 0; j < (int)edges[nodes[i]].size(); ++j) {
if (match[edges[nodes[i]][j]] == -1 &&
(int)edges[edges[nodes[i]][j]].size() < min_degree) {
min_degree = edges[edges[nodes[i]][j]].size();
v = edges[nodes[i]][j];
}
}
if (v >= 0) {
match[nodes[i]] = v;
match[v] = nodes[i];
}
}
}
}
int main() {
int b, c;
scanf("%d %d", &n, &m);
for (int i = 0; i < m; ++i) {
scanf("%d %d", &b, &c);
edges[--b].push_back(--c);
edges[c].push_back(b);
}
fill(act, act + n, true);
fill(match, match + n, -1);
create_random_match();
do {
expand_cycles();
build_alternating_forest();
} while (find_path());
/* printing output */
vector<pair<int, int> > out;
for (int i = 0; i < n; ++i) {
if (match[i] > i) {
out.push_back(make_pair(i, match[i]));
}
}
printf("%d\n", out.size());
for (int i = 0; i < (int)out.size(); ++i) {
printf("%d %d\n", out[i].first + 1, out[i].second + 1);
}
return 0;
}