/** Roman Kolganov, March 2019 */
#include <bits/stdc++.h>
using namespace std;
const int N = 250;
vector<int> g[N];
int mate[N];
int state[N];
int p[N];
int dsu_rank[N];
int repr[N];
int tree_prev[N];
int edge_from[N];
int edge_to[N];
int left_mark[N];
int right_mark[N];
int current_mark = 0;
int get(int v) {
return p[v] == v ? v : (p[v] = get(p[v]));
}
void join(int u, int v) {
u = get(u);
v = get(v);
if (dsu_rank[v] < dsu_rank[u]) {
swap(u, v);
}
p[u] = v;
if (dsu_rank[v] == dsu_rank[u]) {
++dsu_rank[v];
}
}
void promote(int v) {
repr[get(v)] = v;
}
int base(int v) {
return repr[get(v)];
}
void get_path(int from, int to, list<int>& path, bool rev) {
if (from == to || (state[from] == 0 && mate[from] == 0)) {
path.push_front(from);
return;
}
if (state[from] == 0) {
if (rev) {
path.push_front(from);
path.push_front(mate[from]);
get_path(tree_prev[mate[from]], to, path, rev);
} else {
get_path(tree_prev[mate[from]], to, path, rev);
path.push_front(mate[from]);
path.push_front(from);
}
return;
}
if (rev) {
path.push_front(from);
get_path(edge_from[from], mate[from], path, !rev);
get_path(edge_to[from], to, path, rev);
} else {
get_path(edge_to[from], to, path, rev);
get_path(edge_from[from], mate[from], path, !rev);
path.push_front(from);
}
}
void augment(auto& path) {
while (!path.empty()) {
int x = path.front();
path.pop_front();
int y = path.front();
path.pop_front();
mate[x] = y;
mate[y] = x;
}
}
void shrink(vector<int>& cycle, int v, int b, int from, int to) {
for (int w = base(v); w != b; w = base(tree_prev[mate[w]])) {
join(b, w);
join(b, mate[w]);
promote(b);
edge_from[mate[w]] = from;
edge_to[mate[w]] = to;
cycle.push_back(mate[w]);
}
}
bool dfs(int v) {
for (int u : g[v]) {
if (base(u) == base(v) || state[base(u)] == 1) {
continue;
}
if (state[u] == -1) {
if (mate[u] != 0) {
state[u] = 1;
tree_prev[u] = v;
state[mate[u]] = 0;
if (dfs(mate[u])) {
return true;
}
} else {
list<int> path;
get_path(v, 0, path, false);
path.push_front(u);
augment(path);
return true;
}
} else {
vector<int> cycle;
int cv = base(v);
int cu = base(u);
++current_mark;
left_mark[cu] = current_mark;
right_mark[cv] = current_mark;
while (left_mark[cv] != current_mark && right_mark[cu] != current_mark) {
if (mate[cu] != 0) {
cu = base(tree_prev[mate[cu]]);
left_mark[cu] = current_mark;
}
if (mate[cv] != 0) {
cv = base(tree_prev[mate[cv]]);
right_mark[cv] = current_mark;
}
}
int b = left_mark[cv] == current_mark ? cv : cu;
shrink(cycle, v, b, v, u);
shrink(cycle, u, b, u, v);
for (int w : cycle) {
if (dfs(w)) {
return true;
}
}
}
}
return false;
}
int main() {
//freopen("schedule.in", "r", stdin);
//freopen("schedule.out", "w", stdout);
ios_base::sync_with_stdio(false); cin.tie(nullptr);
int n;
cin >> n;
int x, y;
while (cin >> x >> y) {
g[x].push_back(y);
g[y].push_back(x);
}
for (int v = 1; v <= n; ++v) {
if (mate[v] != 0) {
continue;
}
fill_n(state + 1, n, -1);
fill_n(dsu_rank + 1, n, 0);
iota(p + 1, p + n + 1, 1);
iota(repr + 1, repr + n + 1, 1);
state[v] = 0;
dfs(v);
}
vector<pair<int, int>> matching;
for (int v = 1; v <= n; ++v) {
if (mate[v] != 0) {
matching.emplace_back(v, mate[v]);
mate[mate[v]] = 0;
}
}
cout << matching.size() * 2 << '\n';
for (auto [v, u] : matching) {
cout << v << ' ' << u << '\n';
}
}