#include<deque>
#include<queue>
#include<vector>
#include<algorithm>
#include<iostream>
#include<set>
#include<cmath>
#include<tuple>
#include<string>
#include<chrono>
#include<functional>
#include<iterator>
#include<random>
#include<unordered_set>
#include<array>
#include<map>
#include<iomanip>
#include<assert.h>
using namespace std;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
/*
cout<<setprecision(20)
cin.tie(0);
ios::sync_with_stdio(false);
*/
const llint mod=998244353;
const llint big=2.19e15+1;
const long double pai=3.141592653589793238462643383279502884197;
const long double eps=1e-15;
template <class T,class U>void mineq(T& a,U b){if(a>b){a=b;}}
template <class T,class U>void maxeq(T& a,U b){if(a<b){a=b;}}
llint gcd(llint a,llint b){if(a%b==0){return b;}else return gcd(b,a%b);}
llint lcm(llint a,llint b){return a/gcd(a,b)*b;}
template<class T> void SO(T& ve){sort(ve.begin(),ve.end());}
template<class T> void REV(T& ve){reverse(ve.begin(),ve.end());}
llint LBI(vector<llint>&ar,llint in){return lower_bound(ar.begin(),ar.end(),in)-ar.begin();}
llint UBI(vector<llint>&ar,llint in){return upper_bound(ar.begin(),ar.end(),in)-ar.begin();}
vector<vector<int>>go;
vector<int>miti;
int dfs(int ter,int oya,int gol){
	miti.pub(ter);
	if(ter==gol){return 1;}
	for(auto it:go[ter]){
		if(it==oya){continue;}
		if(dfs(it,ter,gol)==1){return 1;}
	}
	if(gol!=-1){miti.pob();}
	return 0;
}
int main(void){
	cin.tie(0);
	ios::sync_with_stdio(false);
	int n,m,i,j,k,h;cin>>n>>m;
	//適当に決めても案外何とかなる説
	static int v[2000]={0};
	static int u[2000]={0};
	static int hen[2000][2000]={0};
	static int ban[2000][2000]={0};
	//小さい->大きい +1 大きい->小さい -1
	go.res(n);
	for(i=0;i<n-1;i++){
		int a,b;cin>>a>>b;
		a--;b--;
		go[a].pub(b);
		go[b].pub(a);
		ban[a][b]=i+1;
		ban[b][a]=-(i+1);
	}
	for(i=0;i<m;i++){
		cin>>v[i]>>u[i];
		v[i]--;u[i]--;
		miti.clear();
		dfs(v[i],-1,u[i]);
		//mitiに道が記されている
		for(j=0;j<(int)miti.size()-1;j++){
			int road=ban[miti[j]][miti[j+1]];
			if(road>0){hen[i][road]=1;}
			else{hen[i][-road]=-1;}
		}
	}
	//hen に1～nまでの向きが入った
	//てきとうにやる
	static int tota[2000]={0};//+1 -2
	static int noko[2000]={0};
	for(i=0;i<m;i++){
		for(j=1;j<n;j++){
			if(hen[i][j]!=0){noko[j]++;}
		}
	}
	static bool used[2000]={};
	for(i=0;i<m;i++){
		if(used[i]){continue;}
		used[i]=true;
		for(h=1;h<n;h++){
			if(hen[i][h]>0){tota[h]|=1;noko[h]--;}
			if(hen[i][h]<0){tota[h]|=2;noko[h]--;}
		}
		//残りが1の辺があればそれを探して向きをつける
		bool recha=false;
		do{
			recha=false;
			for(j=1;j<n;j++){
				if(noko[j]==1&&(tota[j]==1||tota[j]==2)){
					for(k=0;k<m;k++){
						if(used[k]){continue;}
						if(hen[k][j]==0){continue;}
						//会う辺を見つけた!
						recha=true;
						used[k]=true;
						if((tota[j]==1)==(hen[k][j]==1)){
							swap(u[k],v[k]);//逆転させる
							for(h=1;h<n;h++){
								if(hen[k][h]>0){tota[h]|=2;noko[h]--;}
								if(hen[k][h]<0){tota[h]|=1;noko[h]--;}
							}
						}else{
							for(h=1;h<n;h++){
								if(hen[k][h]>0){tota[h]|=1;noko[h]--;}
								if(hen[k][h]<0){tota[h]|=2;noko[h]--;}
							}
						}
						break;
					}
				}
			}
		}while(recha);
	}
	int tano=0;
	for(i=1;i<n;i++){
		if(tota[i]&1){tano++;}
		if(tota[i]&2){tano++;}
	}
	cout<<tano<<endl;
	for(i=0;i<m;i++){cout<<u[i]+1<<" "<<v[i]+1<<endl;}
	return 0;
}

Measured memory_bytes: 31488