#include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <deque>
#include <fstream>
#include <iterator>
#include <set>
#include <map>
#include <unordered_map>
#include <iomanip>
#include <cctype>
#include <string>
#include <cassert>
#include <set>
#include <bitset>
#include <unordered_set>
#include <numeric>
#define all(a) a.begin(), a.end()
#define fast ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define pb push_back
#define ppi pair<int,pair<int,int>>
#define int int64_t
using namespace std;
// /\_/\
// (= ._.)
// / > \>
// encouraging cat
const int INF = 10000000000000000;
//const int mod = 1000000007;
const int mod = 998244353;
const int MAXN = 5e5;
//ifstream fin('xor.in');
//ofstream fout('xor.out');
int n;
int rt = 0;
vector<vector<int>> adj;
int tin[MAXN], tout[MAXN];
int sz[MAXN];
int ptr[MAXN], fin[MAXN];
int timer = 0;
vector<int> leafs;
vector<pair<int,int>> res;
int dfs_sz(int node, int p)
{
int s = 0;
for (auto edge: adj[node])
{
if (edge == p)
{
continue;
}
s += dfs_sz(edge, node);
}
if (adj[node].size() == 1)
{
s++;
}
for (int i = 0;i < adj[node].size();i++)
{
if (p == adj[node][i])
{
adj[node].erase(adj[node].begin() + i);
break;
}
}
sz[node] = s;
return s;
}
void dfs(int node, int p)
{
tin[node] = timer++;
for (auto edge: adj[node])
{
dfs(edge, node);
}
tout[node] = timer;
if (adj[node].size() == 0)
{
leafs.pb(node);
}
}
void calc(int node, int p, int rem)
{
int pos_mx = adj[node][0];
int tot = 0;
for (auto edge: adj[node])
{
if (edge == p)
{
continue;
}
if (sz[edge] > sz[pos_mx])
{
pos_mx = edge;
}
tot += sz[edge];
}
if (sz[pos_mx] > tot - sz[pos_mx] + rem)
{
calc(pos_mx, node, tot - sz[pos_mx] + rem);
}
else
{
vector<int> ot;
for (auto i: leafs)
{
if (tin[i] >= tin[node] && tout[i] <= tout[node])
{
;
}
else
{
ot.pb(i);
}
}
int m = adj[node].size();
vector<vector<int>> sub(adj[node].size());
int ptr = 0;
for (auto i: leafs)
{
int real = adj[node][ptr];
while (ptr < m && !(tin[i] >= tin[real] && tout[i] <= tout[real]) && tin[i] >= tin[real])
{
ptr++;
real = adj[node][ptr];
}
if (ptr == m)
{
break;
}
if (tin[i] >= tin[real] && tout[i] <= tout[real])
{
sub[ptr].pb(i);
}
}
sub.pb(ot);
m++;
priority_queue<pair<int,int>> pq; // sq, ind
for (int i = 0;i < m;i++)
{
if (sub[i].size() != 0)
{
pq.push({sub[i].size(), i});
}
}
while (pq.size() >= 2)
{
int va = pq.top().second;
pq.pop();
int vb = pq.top().second;
pq.pop();
res.pb({sub[va].back(), sub[vb].back()});
sub[va].pop_back();
sub[vb].pop_back();
if (!sub[va].empty())
{
pq.push({sub[va].size(), va});
}
if (!sub[vb].empty())
{
pq.push({sub[vb].size(), vb});
}
}
if (pq.size() == 1)
{
int v = sub[pq.top().second][0];
if (v != leafs[0])
{
res.pb({v, leafs[0]});
}
else
{
res.pb({v, leafs[1]});
}
}
}
}
signed main()
{
cin >> n;
adj.resize(n);
for (int i = 0;i < n - 1;i++)
{
int u,v;
cin >> u >> v;
u--,v--;
adj[u].pb(v);
adj[v].pb(u);
}
if (adj[rt].size() == 1)
{
rt = adj[rt][0];
}
dfs_sz(rt, -1);
dfs(rt, -1);
calc(rt, -1, 0);
cout << res.size() << '\n';
for (auto m: res)
{
cout << m.first + 1 << " " << m.second + 1 << '\n';
}
return 0;
}