#include <bits/stdc++.h>
// iostream is too mainstream
#include <cstdio>
// bitch please
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <cmath>
#include <iomanip>
#include <time.h>
#define dibs reserve
#define OVER9000 1234567890
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define tisic 47
#define soclose 1e-8
#define chocolate win
// so much chocolate
#define patkan 9
#define ff first
#define ss second
#define abs(x) (((x) < 0)?-(x):(x))
#define uint unsigned int
#define dbl long double
#define pi 3.14159265358979323846
using namespace std;
// mylittledoge

using cat = long long;

#ifdef DONLINE_JUDGE
	// palindromic tree is better than splay tree!
	#define lld I64d
#endif

typedef struct {
	int u, v, l, id;
} path;

void DFS(int R, vector< vector<int> > & G, vector<int> & dep, vector<int> & par, vector<int> & seq) {
	seq.push_back(R);
	ALL_THE(G[R], it) if(par[*it] == -1) {
		dep[*it] = dep[R]+1;
		par[*it] = R;
		DFS(*it, G, dep, par, seq);
	}
}

int lca(int u, int v, vector<int> & par, vector<int> & dep) {
	if(dep[u] > dep[v]) swap(u, v);
	while(dep[v] > dep[u]) v = par[v];
	if(v == u) return v;
	while(par[v] != par[u]) v = par[v], u = par[u];
	return par[v];
}

int main() {
	cin.sync_with_stdio(0);
	cin.tie(0);
	cout << fixed << setprecision(10);
	int N, M;
	cin >> N >> M;
	vector< vector<int> > G(N);
	for(int i = 0; i < N-1; i++) {
		int u, v;
		cin >> u >> v;
		G[--u].push_back(--v);
		G[v].push_back(u);
	}
	vector<int> par(N, -1), dep(N, 0), seq;
	par[0] = 0;
	DFS(0, G, dep, par, seq);

	vector< pair<int, int> > rules_e, rules_d; // paths with different directions

	int P = M;
	vector<path> paths(M);
	vector<int> cov(N, 0), U(M), V(M);
	for(int i = 0; i < M; i++) {
		cin >> paths[i].u >> paths[i].v;
		U[i] = paths[i].u, V[i] = paths[i].v;
		paths[i].u--, paths[i].v--;
		paths[i].id = i;
		paths[i].l = lca(paths[i].u, paths[i].v, par, dep);
		int v = paths[i].u;
		while(v != paths[i].l) {
			if(cov[v] == 0) cov[v] |= 1;
			else cov[v] |= 2;
			v = par[v];
		}
		v = paths[i].v;
		while(v != paths[i].l) {
			if(cov[v] == 0) cov[v] |= 1;
			else cov[v] |= 2;
			v = par[v];
		}
	}
	vector<int> endpts(N);
	while(P > 1) {
		// find endpoint
		for(int i = 0; i < P; i++) if(paths[i].u == paths[i].v) {
			swap(paths[i], paths[P-1]);
			P--;
			i--;
		}
		if(P <= 1) break;
		for(int i = 0; i < N; i++) endpts[i] = 0;
		for(int i = 0; i < P; i++) endpts[paths[i].u]++, endpts[paths[i].v]++;
		int ve = N-1;
		while(endpts[seq[ve]] == 0) ve--;
		ve = seq[ve];
		if(endpts[ve] == 1) {
			int p_cur = -1;
			for(int i = 0; i < P; i++) if(paths[i].u == ve || paths[i].v == ve) p_cur = i;
			if(paths[p_cur].v == ve) paths[p_cur].v = par[paths[p_cur].v];
			else paths[p_cur].u = par[paths[p_cur].u];
			continue;
		}
		int p_cur[2] = {-1, -1};
		for(int i = 0; i < P; i++) if(paths[i].u == ve || paths[i].v == ve) {
			if(p_cur[0] == -1) p_cur[0] = i;
			else {
				p_cur[1] = i;
				break;
			}
		}
		bool pos[2];
		for(int k = 0; k < 2; k++) pos[k] = (paths[p_cur[k]].u == ve);
		path p_nw;
		if(pos[0] == pos[1]) {
			rules_d.push_back({paths[p_cur[0]].id, paths[p_cur[1]].id});
			if(pos[0]) {
				p_nw.u = paths[p_cur[0]].v;
				p_nw.v = paths[p_cur[1]].v;
				p_nw.id = paths[p_cur[1]].id;
			}
			else {
				p_nw.u = paths[p_cur[0]].u;
				p_nw.v = paths[p_cur[1]].u;
				p_nw.id = paths[p_cur[0]].id;
			}
		}
		else {
			rules_e.push_back({paths[p_cur[0]].id, paths[p_cur[1]].id});
			if(pos[0]) {
				p_nw.u = paths[p_cur[1]].u;
				p_nw.v = paths[p_cur[0]].v;
				p_nw.id = paths[p_cur[1]].id;
			}
			else {
				p_nw.u = paths[p_cur[0]].u;
				p_nw.v = paths[p_cur[1]].v;
				p_nw.id = paths[p_cur[0]].id;
			}
		}
		p_nw.l = lca(p_nw.u, p_nw.v, par, dep);
		swap(paths[p_cur[1]], paths[P-1]);
		swap(paths[p_cur[0]], paths[P-2]);
		P--;
		paths[P-1] = p_nw;
	}

	int ans_cnt = 0;
	for(int i = 1; i < N; i++) ans_cnt += (cov[i] & 1) + (cov[i] >> 1);
	vector<int> ans(M, -1);
	queue<int> q;
	for(int i = 0; i < M; i++) if(ans[i] == -1) {
		ans[i] = 0;
		q.push(i);
		while(!q.empty()) {
			ALL_THE(rules_d, it) if(it->ff == q.front() || it->ss == q.front()) {
				if(ans[it->ff] != -1 && ans[it->ss] != -1) continue;
				ans[it->ff+it->ss-q.front()] = 1 - ans[q.front()];
				q.push(it->ff+it->ss-q.front());
			}
			ALL_THE(rules_e, it) if(it->ff == q.front() || it->ss == q.front()) {
				if(ans[it->ff] != -1 && ans[it->ss] != -1) continue;
				ans[it->ff+it->ss-q.front()] = ans[q.front()];
				q.push(it->ff+it->ss-q.front());
			}
			q.pop();
		}
	}
	cout << ans_cnt << "\n";
	for(int i = 0; i < M; i++) {
		if(ans[i] == 0) cout << U[i] << " " << V[i] << "\n";
		else cout << V[i] << " " << U[i] << "\n";
	}
	return 0;
}

// look at my code
// my code is amazing


Measured memory_bytes: 640