#include<bits/stdc++.h>
using namespace std;

#define REP(i, n) for(int i =0; i < n; ++i)
#define EPSILON (1e-7);

bool is_zero(double x) { return abs(x) <= EPSILON; }
bool is_negative(double x) { return x < -EPSILON; }

template<class T> bool are_equal(const complex<T> &A, const complex<T> &B) {
	return is_zero(real(B) - real(A)) && is_zero(imag(A) - imag(B));
}

template<class T> T cross_product(const complex<T> &A, const complex<T> &B) {
	return real(A) * imag(B) - real(B) * imag(A);
}

template<class T> bool clockwise(const complex<T> &A, const complex<T> &B, const complex<T> &C) {
	return is_negative(cross_product(B - A, C - A));
}
template<class T> bool counterclockwise(const complex<T> &A, const complex<T> &B, const complex<T> &C) {
	return clockwise(C, B, A);
}

template<class T> bool compare_XY(const complex<T> &A, const complex<T> &B) {
	if(!is_zero(real(A) - real(B))) return (is_negative(real(A) - real(B)));
	return is_negative(imag(A) - imag(B));
}
template<class T> bool compare_YX(const complex<T> &A, const complex<T> &B) {
	if(!is_zero(imag(A) - imag(B))) return (is_negative(imag(A) - imag(B)));
	return is_negative(real(A) - real(B));
}

template<class T> int signum(const T &A) { 
	if(is_zero(A)) return 0;
	if(is_negative(A)) return -1;
	return 1;
}

template<class T> T square_size(const complex<T> &A) { return real(A) * real(A) + imag(A) * imag(A); }

template<class T> bool compare_arg(const complex<T> &A, const complex<T> &B) {
	if(are_equal(B, complex<T>(0,0))) return 0;
	if(are_equal(A, complex<T>(0,0))) return 1;
	int sgnA = signum(imag(A));
	int sgnB = signum(imag(B));
	if(sgnA == 0) if(signum(real(A)) < 0) sgnA = 2;
	if(sgnB == 0) if(signum(real(B)) < 0) sgnB = 2;
	if(sgnA != sgnB) return sgnA < sgnB;
	if(counterclockwise(complex<T>(0,0), A, B)) return 1;
	if(clockwise(complex<T>(0,0), A, B)) return 0;
	return square_size(A) < square_size(B);
}

template<class T> bool compare_arg_pair(const pair<complex<T>,int> &AA, const pair<complex<T>,int> &BB) {
	return compare_arg<T>(AA.first, BB.first);
}

template<class T> vector<complex<T>> convex_hull(vector<complex<T>> V) {
	if(V.size() == 2) if(are_equal(V[0], V[1])) V.pop_back();
	if(V.size() <= 2) return V;
	
	sort(V.begin(), V.end(), compare_YX<T> );
	complex<T> offset = V[0];
	for(unsigned int i = 0; i < V.size(); i++) V[i] -= offset;
	sort(V.begin() + 1, V.end(), compare_arg<T>);
	
	int count = 2;
	vector<int> hull(V.size() + 2);
	for(unsigned int i=0; i < 2; i++) hull[i] = i;
	for(unsigned int i=2; i < V.size(); i++) {
		while(count >= 2&& !counterclockwise(V[hull[count-2]], V[hull[count-1]], V[i])) count--;
		hull[count++] = i;
	}
	vector<complex<T>> res;
	for(int i = 0; i < count; i++) res.push_back(V[hull[i]] + offset);
	if(res.size()==2) if(are_equal(res[0], res[1])) res.pop_back();
	return res;
}


vector<complex<long long> > pt;
vector<int> sz;
vector<vector<int> > sons;
vector<int> v, w;
int N;
int cnt = 0;

void solve(vector<int> pos, int x, int tree){
	long long mi = 7 * 1e18;
	cnt++;
	int nw; 
	int grc; 
	if(x != -1){
		for(int i = 0; i<pos.size(); i++){
			if(mi > square_size(pt[x] - pt[pos[i]])){
				mi = min(mi, square_size(pt[x] - pt[pos[i]]));
				grc = i;
			}
		}
		if(cnt > 1) cout << x << " " << pos[grc] << endl;	
	
		nw  = pos[grc];
		for(int i = grc + 1; i<pos.size(); i++){
			pos[i - 1]  = pos[i];
		}
		pos.pop_back();
	}
	
	else{
		
	}	

	vector<pair<complex<long long>, int> > v;
	if(sons[tree].size() == 0) return;
	for(int i = 0; i<pos.size(); i++){
		v.push_back(make_pair(pt[nw] - pt[pos[i]], pos[i]));
	}
	sort(v.begin(), v.end(), compare_arg_pair<long long>);
	int ptr = 0;
	vector<int> ret;
	
	for(int i = 0; i<sons[tree].size(); i++){
		for(int j = 0; j<sz[sons[tree][i]]; j++){
			ret.push_back(v[ptr].second);
			ptr++;
		}

		solve(ret, nw, sons[tree][i]); 
	}
	
}

int main(){
	cin >> N;
	int p[N];
	p[0] = 0;
	int rem[N]; 
	vector<int> g[N];
	sons.resize(N);
	pt.resize(N);
	sz.resize(N);

	int x, y;
	for(int i = 0; i<N - 1; i++){
		cin >> x >> y;
		g[x].push_back(y);
		g[y].push_back(x);
	}

	vector<int> dfs;
	int vis[N];
	fill(vis, vis + N, 0);
fill(rem, rem + N, 0);
	vis[0] = 1;
	dfs.push_back(0);
	while(!dfs.empty()){
		x = dfs.back();
		dfs.pop_back();
		for(int i = 0; i<g[x].size(); i++){	
			if(vis[g[x][i]] == 0){
				vis[g[x][i]] = 1;
				p[g[x][i]] = x;
				dfs.push_back(g[x][i]);
				sons[x].push_back(g[x][i]);
				rem[x]++;			
			}
		}	
	}

	for(int i = 0; i<N; i++){
		if(rem[i] == 0){
			dfs.push_back(i);
			sz[i] = 1;
		}
	}
	
	while(!dfs.empty()){
		x = dfs.back();
		dfs.pop_back();
			
		rem[p[x]] --;
		if(rem[p[x]] == 0){
			y = 1;
			dfs.push_back(p[x]);
			for(int i = 0; i<sons[p[x]].size(); i++){
				y += sz[sons[p[x]][i]];
			}

			sz[p[x]] = y;		
		}

		
	}

	//cout << sz[0] << endl;
	for(int i = 0; i<N; i++){
		w.push_back(i);
	}
	int kap, m;
	m = 2*1e9;

	for(int i = 0; i<N; i++){
		cin >> x >> y;
		pt[i] = {x, y};		
	}

		for(int i = 0; i<N; i++){
			if(m > imag(pt[w[i]])){
				m = imag(pt[w[i]]);
				kap = i;
			}
		}

	solve(w, kap, 0);

	 
}

