#include <cstdio>
#include <vector>
#include <cstring>

using namespace std;
const int Max_N(2050);
const int Max_M(2050);
typedef pair<int, int> pil;
#define mp make_pair
#define fi first
#define se second

namespace io
{
	const int SIZE = (1 << 21) + 1;
	char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
	#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
	inline void flush (){fwrite (obuf, 1, oS - obuf, stdout);oS = obuf;}
	inline void putc (char x){*oS ++ = x;if (oS == oT) flush ();}
	template <class I>
	inline void gi (I &x) {for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
		for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;}
	template <class I>
	inline void print (I x){
		if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;while(x) qu[++ qr] = x % 10 + '0',  x /= 10;while (qr) putc (qu[qr--]);}
	struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io::gi;
using io::putc;
using io::print;

int N, M, Head[Max_N], Total, To[Max_N << 1], Next[Max_N << 1], A[Max_M], B[Max_M], Dir[Max_M], Father[Max_N], Deep[Max_N], Son[Max_N], Q[Max_N];
int Cnt1[Max_N], Cnt2[Max_N], Ans;

inline void Add_Edge(int s, int t)
{
	++Total, To[Total] = t, Next[Total] = Head[s], Head[s] = Total;
}

void dfs(int u)
{
	for (int i = Head[u], v;i;i = Next[i])
		if ((v = To[i]) != Father[u])
			Father[v] = u, Deep[v] = Deep[u] + 1, dfs(v), ++Son[u];
}

bool done[Max_N];

int LCA(int u, int v)
{
	memset(done, false, sizeof(done));
	for (;u;u = Father[u])
		done[u] = true;
	for (;v;v = Father[v])
		if (done[v])
			return v;
}

struct path
{
	int s, t;
	vector<pil> v;
};
vector<path> V[2], T;

void getAns(int u)
{
	for (int i = Head[u], v;i;i = Next[i])
		if ((v = To[i]) != Father[u])
			getAns(v), Cnt1[u] += Cnt1[v], Cnt2[u] += Cnt2[v];
	Ans += (Cnt1[u] > 0) + (Cnt2[u] > 0);
}

int main()
{
	gi(N), gi(M);
	for (int i = 1, u, v;i != N;++i)
		gi(u), gi(v), Add_Edge(u, v), Add_Edge(v, u);
	dfs(1);
	for (int i = 1;i <= M;++i)
	{
		gi(A[i]), gi(B[i]);
		path a;
		a.s = A[i], a.t = B[i], a.v.push_back(mp(i, 0)), V[0].push_back(a);
	}
	for (int u = 1;u <= N;++u)
		if (!Son[u])
			Q[++Q[0]] = u;
	for (int ft = 1, now = 1, nxt = 0, u;ft <= Q[0];)
	{
		u = Q[ft++], now ^= 1, nxt ^= 1, V[nxt].clear(), T.clear();
		if (u == 1)
			break;
		if ((--Son[Father[u]]) == 0)
			Q[++Q[0]] = Father[u];
		for (int i = 0;i < V[now].size();++i)
			if (V[now][i].s == u || V[now][i].t == u)
			{
				T.push_back(V[now][i]);
				if (V[now][i].t == u)
				{
					swap(T.back().s, T.back().t);
					for (int j = 0;j < T.back().v.size();++j)
						T.back().v[j].se ^= 1;
				}
			}
			else
				V[nxt].push_back(V[now][i]);
		while (T.empty() == false)
			if (T.size() == 1)
			{
				path t = T.back();
				T.pop_back();
				if ((t.s = Father[t.s]) != t.t)
					V[nxt].push_back(t);
				else
					for (int j = 0;j < t.v.size();++j)
						Dir[t.v[j].fi] = t.v[j].se;
			}
			else
			{
				path t1 = T.back();
				T.pop_back();
				path t2 = T.back();
				T.pop_back();
				if (t1.t != t2.t)
				{
					path t;
					t.s = t1.t, t.t = t2.t;
					for (int j = 0;j < t1.v.size();++j)
						t1.v[j].se ^= 1, t.v.push_back(t1.v[j]);
					for (int j = 0;j < t2.v.size();++j)
						t.v.push_back(t2.v[j]);
					V[nxt].push_back(t);
				}
				else
				{
					for (int j = 0;j < t1.v.size();++j)
						Dir[t1.v[j].fi] = (t1.v[j].se ^ 1);
					for (int j = 0;j < t2.v.size();++j)
						Dir[t2.v[j].fi] = t2.v[j].se;
				}
			}
	}
	for (int i = 1, lca;i <= M;++i)
	{
		lca = LCA(A[i], B[i]);
		if (Dir[i] == 0)
			++Cnt1[A[i]], --Cnt1[lca], ++Cnt2[B[i]], --Cnt2[lca];
		else
			++Cnt1[B[i]], --Cnt1[lca], ++Cnt2[A[i]], --Cnt2[lca];
	}
	getAns(1);
	print(Ans), putc('\n');
	for (int i = 1, lca;i <= M;++i)
	{
		if (Dir[i] == 0)
			print(A[i]), putc(' '), print(B[i]);
		else
			print(B[i]), putc(' '), print(A[i]);
		putc('\n');
	}
	return 0;
}

Measured memory_bytes: 2688