#include using namespace std; #define For(i, n) for (int i = 0; i <(n); i++) typedef long long ll; #define st first #define nd second typedef pair < int, int > PII; typedef long long ll; const int N = 1010; int parent[N]; pair < ll, ll > cur; struct point { ll first; ll second; int ix; point() { first = 0; second = 0; ix = -1; } point(ll fst, ll snd, int _ix) { first = fst; second = snd; ix = _ix; } ll Wektor (point p1, point p2) { return p1.first * p2.second - p1.second * p2.first; } bool operator < (point p) { point p1 = point(first - cur.first, second - cur.second, -1); point p2 = point(p.first - cur.first, p.second - cur.second, -1); return Wektor(p2, p1) > 0; } }; //typedef pair point; point points[N]; vector G[N]; int sub_size[N]; int parents[N]; int dfs(int x, int p) { parents[x] = p; int cnt = 1; for (int y : G[x]) { if (y == p) continue; cnt += dfs(y, x); } sub_size[x] = cnt; return cnt; } vector> result; void go(int parent, int curr, point parent_p, point curr_p, vector ps) { if (parent_p.ix != -1) { result.push_back({parent_p.ix, curr_p.ix}); } if (sub_size[curr] == 1) return; cur.first = curr_p.first; cur.second = curr_p.second; sort(ps.begin(), ps.end()); int ind = 0; for (int y : G[curr]) { if (y == parent) continue; auto p = ps[ind]; vector next_ps; for (int i = 1; i < sub_size[y]; i++) { next_ps.push_back(ps[ind + i]); } go(curr, y, curr_p, p, next_ps); ind += sub_size[y]; } } int main () { ios::sync_with_stdio(0); int n; cin >> n; For (i, n - 1) { int a, b; cin >> a >> b; G[a].push_back(b); G[b].push_back(a); } point lowest = point(1<<30, 1<<30, -1); For (i, n) { cin >> points[i].first >> points[i].second; points[i].ix = i; if (points[i].second < lowest.second || (points[i].second == lowest.second && points[i].first < lowest.first)) { lowest = points[i]; } } dfs(0, -1); vector ps; For (i, n) { if (i == lowest.ix) continue; ps.push_back(points[i]); } go(-1, 0, point(), lowest, ps); for (auto p : result) { cout << p.first << " " << p.second << "\n"; } // go }