#include <algorithm>  
#include <iostream>  
#include <sstream>  
#include <string>  
#include <cstring>
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <cstdio>  
#include <cstdlib>  
#include <cctype>  
#include <cmath>  
#include <list>  
#include <cassert>
#include <ctime>
#include <climits>
using namespace std;

#define PB push_back  
#define MP make_pair  
#define SZ(v) ((int)(v).size())  
#define FOR(i,a,b) for(int i=(a);i<(b);++i)  
#define REP(i,n) FOR(i,0,n)  
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)  
#define REPE(i,n) FORE(i,0,n)  
#define FORSZ(i,a,v) FOR(i,a,SZ(v))  
#define REPSZ(i,v) REP(i,SZ(v))  
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); }

const int MAXN = 2000;
const int MAXQ = 2000;
const int MAXLG = 10;

int n;
vector<int> adj[MAXN];
int nq;
int qorig[MAXQ][2];

int par[MAXN];
int dep[MAXN];
bool alive[MAXN];
int nchildsalive[MAXN];
int up[MAXN][MAXLG + 1];

int qleaf[MAXN], qleaftail, qleafhead;
set<int> qend[MAXN];
int qcur[MAXQ][2];
int qdir[MAXQ];
int qrel[MAXQ], qrelcnt;

int qans[MAXQ][2];
bool visitup[MAXN], visitdown[MAXN];

void dfsinit(int at) {
	dep[at] = par[at] == -1 ? 0 : dep[par[at]] + 1; alive[at] = true; nchildsalive[at] = 0;
	up[at][0] = par[at] == -1 ? at : par[at]; REP(k, MAXLG) up[at][k + 1] = up[up[at][k]][k];
	REPSZ(i, adj[at]) {
		int to = adj[at][i]; if (to == par[at]) continue;
		par[to] = at; dfsinit(to); nchildsalive[at] += alive[to] ? 1 : 0;
	}
}
int calclca(int a, int b) {
	if (dep[a] < dep[b]) swap(a, b);
	for (int k = MAXLG; k >= 0; --k) if (dep[up[a][k]] >= dep[b]) a = up[a][k];
	for (int k = MAXLG; k >= 0; --k) if (up[a][k] != up[b][k]) a = up[a][k], b = up[b][k];
	return a == b ? a : up[a][0];
}
int calcsplit(int at, int to1, int to2) {
	int lca1 = calclca(at, to1), lca2 = calclca(at, to2);
	if (lca1 != lca2) {
		return dep[lca1] > dep[lca2] ? lca1 : lca2;
	} else {
		return calclca(to1, to2);
	}
}
int calcdist(int a, int b) {
	int lca = calclca(a, b);
	return dep[a] + dep[b] - 2 * dep[lca];
}

void mark(int a, int b) {
	while (a != b) {
		if (dep[a] > dep[b]) {
			visitdown[a] = true;
			a = par[a];
		} else {
			visitup[b] = true;
			b = par[b];
		}
	}
}


void run() {
	scanf("%d%d", &n, &nq);
	REP(i, n - 1) { int a, b; scanf("%d%d", &a, &b); --a, --b; adj[a].PB(b); adj[b].PB(a); }
	REP(i, nq) REP(j, 2) scanf("%d", &qorig[i][j]), --qorig[i][j];

	par[0] = -1; dfsinit(0);
	qleaftail = qleafhead = 0; REP(i, n) if (nchildsalive[i] == 0) qleaf[qleafhead++] = i;
	REP(i, nq) REP(j, 2) qcur[i][j] = qorig[i][j], qend[qcur[i][j]].insert(i);
	qrelcnt = 0;
	while (qleaftail < qleafhead) {
		int at = qleaf[qleaftail++]; assert(alive[at]);
		//printf("at=%d\n", at + 1);
		while (SZ(qend[at]) >= 2) {
			int q1 = *qend[at].begin(); REP(i, 2) assert(alive[qcur[q1][i]]), qend[qcur[q1][i]].erase(q1);
			int q2 = *qend[at].begin(); REP(i, 2) assert(alive[qcur[q1][i]]), qend[qcur[q2][i]].erase(q2);
			int idx1 = -1; REP(i, 2) if (qcur[q1][i] == at) { assert(idx1 == -1); idx1 = i; } assert(idx1 != -1);
			int idx2 = -1; REP(i, 2) if (qcur[q2][i] == at) { assert(idx2 == -1); idx2 = i; } assert(idx2 != -1);
			int to1 = qcur[q1][1 - idx1], to2 = qcur[q2][1 - idx2];
			//printf("\tq1=%d q2=%d\n", q1, q2);
			if (to1 == to2) {
				qdir[q1] = 0; // any direction is fine
				qdir[q2] = idx1 != idx2 ? 0 : 1; // opposite direction
			} else {
				//int split = calcsplit(at, to1, to2);
				qcur[q1][idx1] = to2; REP(i, 2) qend[qcur[q1][i]].insert(q1);
				qdir[q2] = (idx1 != idx2 ? -1 : +1)* (q1 + 1);
				qrel[qrelcnt++] = q2;
			}
		}
		if (SZ(qend[at]) >= 1) {
			int q1 = *qend[at].begin(); REP(i, 2) assert(alive[qcur[q1][i]]), qend[qcur[q1][i]].erase(q1);
			int idx1 = -1; REP(i, 2) if (qcur[q1][i] == at) { assert(idx1 == -1); idx1 = i; } assert(idx1 != -1);
			int to = qcur[q1][1 - idx1];
			if (to == par[at]) {
				qdir[q1] = 0; // any direction is fine
			} else {
				assert(alive[par[at]]);
				qcur[q1][idx1] = par[at]; REP(i, 2) qend[qcur[q1][i]].insert(q1);
			}
		}
		assert(SZ(qend[at]) == 0);
		alive[at] = false;
		if (par[at] != -1 && --nchildsalive[par[at]] == 0) qleaf[qleafhead++] = par[at];
	}
	//printf("qdir:"); REP(i, nq) printf(" %d", qdir[i]); puts("");
	//printf("qrel:"); REP(i, qrelcnt) printf(" %d", qrel[i]); puts("");
	for (int i = qrelcnt - 1; i >= 0; --i) {
		int q2 = qrel[i], q1 = abs(qdir[q2]) - 1; bool same = qdir[q2] < 0;
		qdir[q2] = same ? qdir[q1] : 1 - qdir[q1];
	}
	//printf("qdir:"); REP(i, nq) printf(" %d", qdir[i]); puts("");

	REP(i, nq) qans[i][0] = qorig[i][qdir[i]], qans[i][1] = qorig[i][1 - qdir[i]];
	REP(i, n) visitup[i] = visitdown[i] = false;
	REP(i, nq) mark(qans[i][0], qans[i][1]);
	int ans = 0; REP(i, n) ans += (visitup[i] ? 1 : 0) + (visitdown[i] ? 1 : 0);
	printf("%d\n", ans);
	REP(i, nq) printf("%d %d\n", qans[i][0] + 1, qans[i][1] + 1);
}

int main() {
	run();
	return 0;
}


Measured memory_bytes: 896