/*
  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;
}
