import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.StringTokenizer; /** * ICPC Central Europe Regional Contest 2018 * Incorrect solution: Trees Gump *

* This solution compares angles absolutely (it does not take into account the "uplink" direction) * and may therefore generate crossed links. * * @author Martin Kacer */ public class TreeGumpWrong1 { StringTokenizer st = new StringTokenizer(""); BufferedReader input = new BufferedReader(new InputStreamReader(System.in)); boolean hasNextToken() { try { while (!st.hasMoreTokens()) { String line = input.readLine(); if (line == null) return false; st = new StringTokenizer(line); } } catch (IOException ex) { throw new RuntimeException(ex); } return true; } String nextToken() { return (!hasNextToken()) ? null : st.nextToken(); } int nextInt() { return Integer.parseInt(nextToken()); } public static void main(String[] args) { new TreeGumpWrong1().run(); } static class Point { final int idx; final long x, y; Point(int idx, long x, long y) { this.idx = idx; this.x = x; this.y = y; } } static class CompareByAngle implements Comparator { final Point origin; CompareByAngle(Point origin) { this.origin = origin; } public int compare(Point p1, Point p2) { return Double.compare(Math.atan2(p1.y - origin.y, p1.x - origin.x), Math.atan2(p2.y - origin.y, p2.x - origin.x)); } } List> graph; Point[] points; int[] mapping, subsize; void run() { int n = nextInt(); graph = new ArrayList<>(n); for (int i = 0; i < n; ++i) graph.add(new ArrayList<>()); for (int i = 1; i < n; ++i) { int a = nextInt(), b = nextInt(); graph.get(a).add(b); graph.get(b).add(a); } points = new Point[n]; mapping = new int[n]; subsize = new int[n]; for (int i = 0 ; i < n; ++i) points[i] = new Point(i, nextInt(), nextInt()); Arrays.sort(points, 0, n, (a,b) -> Long.compare(a.y, b.y)); calcSubSize(0, -1); process(0, -1, 0, n); for (int a = 0; a < n; ++a) for (int b : graph.get(a)) if (a < b) { System.out.println(points[mapping[a]].idx + " " + points[mapping[b]].idx); } } int calcSubSize(int root, int parent) { int res = 1; for (int n : graph.get(root)) if (n != parent) res += calcSubSize(n, root); return subsize[root] = res; } void process(int root, int parent, int fromIdx, int toIdx) { mapping[root] = fromIdx; int curidx = fromIdx+1; Arrays.sort(points, curidx, toIdx, new CompareByAngle(points[fromIdx])); for (int n : graph.get(root)) if (n != parent) { process(n, root, curidx, curidx + subsize[n]); curidx += subsize[n]; } } }