#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
int n,x,y,a[10000],b[10000],c[10000],siz[10000],ans[10000];
int first[10000],nxt[10000],go[10000],tot,top;
int add(int x,int y){
    nxt[++tot]=first[x]; first[x]=tot; go[tot]=y;
}
int pre_dfs(int x,int father){
    for(int i=first[x];i;i=nxt[i])
	if(go[i]!=father)
	    siz[x]+=pre_dfs(go[i],x);
    return ++siz[x];
}

int askx(int x){
    return a[x]-a[c[top]];
}

int asky(int x){
    return b[x]-b[c[top]];
}

int mysort(int x,int y){
    return 1ll*askx(x)*asky(y)<1ll*askx(y)*asky(x);
}

int dfs(int x,int father){
    top++;
    for(int i=1;i<siz[x];i++)
	if(a[c[top]]>a[c[top+i]])
	    swap(c[top],c[top+i]);
    ans[c[top]]=x;
    if(siz[x]==1) return 0;;
    //for(int i=1;i<=n;i++) printf("%d ",c[i]);
    sort(c+top+1,c+top+siz[x],mysort);
    //for(int i=1;i<=n;i++) printf("%d ",c[i]);
    //printf("| %d %d %d\n",x,top,siz[x]);
    for(int i=first[x];i;i=nxt[i])
	if(go[i]!=father){
	    dfs(go[i],x);
	}
}

int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
	scanf("%d%d",&x,&y);
	add(x,y);
	add(y,x);
    }
    for(int i=1;i<=n;i++){
	scanf("%d%d",&a[i],&b[i]);
	c[i]=i;
//	if(a[i]<a[c[1]]) swap(c[i],c[1]);
    }
    //return 0;
    pre_dfs(1,0);
    dfs(1,0);
    for(int i=1;i<=n;i++) printf("%d ",ans[i]);
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2040;

int n,ans[N];//ans:posnumber-> treenumber
struct node
{
	ll x,y;
	int id;
}a[N],nowp;

bool cmp(node p,node q)
{
	ll px=p.x-nowp.x;
	ll py=p.y-nowp.y;
	ll qx=q.x-nowp.x;
	ll qy=q.y-nowp.y;
	if(py>=0&&qy<=0) return 0;
	if(py<=0&&qy>=0) return 1;
	return py*qx<px*qy;//有乘法，要开long long
}

int first[N*4],nxt[N*4],point[N*4],e=0;
void add_edge(int x,int y)
{
	point[++e]=y;
	nxt[e]=first[x];
	first[x]=e;
}

int s[N];
int dfs_size(int u,int f)
{
	s[u]=1;
	for(int i=first[u];i!=-1;i=nxt[i])
	{
		int p=point[i];
		if(p==f) continue;
		s[u]+=dfs_size(p,u);
	}
	return s[u];
}

void dfs(int l,int r,int u,int f)
{
	int pos=l;
	for(int i=l+1;i<=r;i++)
	{
		if(a[pos].x>a[i].x||(a[pos].x==a[i].x&&a[i].y<a[pos].y)) pos=i;
	}
	swap(a[pos],a[l]);//a[pos] has already become a[l]
	ans[a[l].id]=u;
	nowp=a[l];
	sort(a+l+1,a+r+1,cmp);
	int sum=l+1;
	for(int i=first[u];i!=-1;i=nxt[i])
	{
		int p=point[i];
		if(p==f) continue;
		dfs(sum,sum+s[p]-1,p,u);
		sum+=s[p];
	}
}

void init()
{
	memset(first,-1,sizeof(first));
	memset(nxt,-1,sizeof(nxt));
	scanf("%lld",&n);
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		add_edge(u,v);
		add_edge(v,u);
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a[i].x,&a[i].y);
		a[i].id=i;
	}
}

int main()
{
	init();
	dfs_size(1,-1);
	dfs(1,n,1,-1);
	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
	return 0;
}


#include <bits/stdc++.h>

#define M_PI 3.14159265358979323846
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define mp make_pair
#define FILE "file"

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int INF = numeric_limits<int>::max();
const ll LLINF = numeric_limits<ll>::max();
const ull ULLINF = numeric_limits<ull>::max();

struct pt
{
    ll x, y;
    pt() = default;
    pt(ll x, ll y) : x(x), y(y) {}
    bool operator < (const pt a) const
    {
        if(x == a.x)
            return y < a.y;
        return x < a.x;
    }
};

int n;
vector<vector<int>> g;
vector<pair<pt, int>> pts;
int sz[1510], ans[1510];

int dfs(int v, int p)
{
    sz[v] = 1;
    for(int& to: g[v])
        if(to != p)
            sz[v] += dfs(to, v);
    return sz[v];
}

int current = 0;

bool cmp(pair<pt, int> a, pair<pt, int> b)
{
    return (a.first.x - pts[current].first.x) * (b.first.y - pts[current].first.y) - (a.first.y - pts[current].first.y) * (b.first.x - pts[current].first.x) > 0;
}

void go(int v, int p, int l, int r)
{
    if(l == r)
        ans[pts[l].second] = v + 1;
    else
    {
        ans[pts[l].second] = v + 1;
        int k = l + 1;
        current = l;
        sort(pts.begin() + k, pts.begin() + r + 1, cmp);
        for(int to: g[v])
        {
            if(to == p)
                continue;
            go(to, v, k, k + sz[to] - 1);
            k += sz[to];
        }
    }
}

int main()
{
//    freopen(FILE".in", "r", stdin);
//    freopen(FILE".out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n;
    g.resize(n);
    for(int i = 0; i < n - 1; i++)
    {
        int a, b;
        cin >> a >> b;
        a--, b--;
        g[a].pb(b);
        g[b].pb(a);
    }
    pts.resize(n);
    for(int i = 0; i < n; i++)
    {
        ll x, y;
        cin >> x >> y;
        pts[i] = mp(pt(x, y), i);
    }
    sort(all(pts));
    dfs(0, -1);
    sort(pts.begin() + 1, pts.end(), cmp);
    go(0, -1, 0, pts.size() - 1);
    for(int i = 0; i < n; i++)
        cout << ans[i] << " ";
    return 0;
}


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>

using namespace std;

#define rep(i, l, r) for(int i = l; i <= r; i++)
#define fi first
#define se second

#define MAXN 2*1599
int Count = 0;
int L[MAXN];
int Next[MAXN];
int H[MAXN];
int X[MAXN];
int Y[MAXN];
int U[MAXN];
int Visit[MAXN];
int Visit1[MAXN];
int V[MAXN];
int n;
int S[MAXN];
int Size[MAXN];
pair<long double, int> Ang[MAXN];

void getSize(int root) {
	int sum = 1;
	Visit[root] = 1;
	for(int idx = H[root]; idx; idx = Next[idx]) {
		int u = L[idx];
		if (Visit[u]) continue;
		//~ cout << root << ":" << u << endl;
		getSize(u);
		sum += Size[u];
	}
	Size[root] = sum;
}

void addLink(int u, int v) {
	L[++Count] = v;
	Next[Count] = H[u];
	H[u] = Count;
}

long double getAngle(int u, int v) {
	if (u==v) return -2;
	long double dx = X[v] - X[u];
	long double dy = Y[v] - Y[u];
	//~ cout << dx << dy;

	return dy*1.0/sqrtl(dx*dx + dy*dy);
}

void divide(int l, int r, int root) {
	int min = l;
	rep(i, l+1, r)
		if (make_pair(X[Ang[i].se], Y[Ang[i].se]) <
			make_pair(X[Ang[min].se], Y[Ang[min].se]))
			min = i;
	swap(Ang[l], Ang[min]);
	S[Ang[l].se] = root;
	Visit1[root] = 1;
	rep(i, l, r)
		Ang[i].fi = getAngle(Ang[l].se, Ang[i].se);

	sort(Ang+l+1, Ang+1+r);
	//~ rep(i, l , r) cout << Ang[i].fi << ":" << Ang[i].se << " ";
	//~ cout << endl;
	int cl = l+1;
	for(int idx = H[root]; idx; idx = Next[idx]) {
		int u = L[idx];
		if (Visit1[u]) continue;
		divide(cl, cl + Size[u] - 1, u);
		cl += Size[u];
	}
}

int main() {

	cin >> n;
	rep(i, 1, n-1) {
		cin >> U[i] >> V[i];
		addLink(U[i], V[i]);
		addLink(V[i], U[i]);
	}

	rep(i, 1, n) cin >> X[i] >> Y[i];
	getSize(1); // Size array

	int min = 1;
	rep(i, 2, n) if (make_pair(X[i],Y[i]) < make_pair(X[min], Y[min]))
		min = i;
	//~ cout << X[min] << ":" << Y[min] << endl;

	//~ cout <<"HEllp" << endl;
	rep(i, 1, n) Ang[i] = make_pair(0, i);
	swap(Ang[1], Ang[min]);
	divide(1, n, 1);

	rep(i, 1, n-1)
		cout << S[i] << " ";
	cout << S[n] << endl;

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int INF = 1e9+7;
const int N = 1501;

int n,nxt[N<<1],h[N],vet[N<<1],num[N],f[N],d[N],fa[N],siz[N],en;

struct Point{
    int a,b,c;double tan;
}P[N],st;

vector <Point> vec;

double tanj(int x,int y,int x1,int y1){
    return (double)(y1-y)/(x1-x);
}

bool cmp1(Point x,Point y){
    return x.a<y.a;
}

bool cmp2(Point x,Point y){
    return (long long)(x.b-st.b)*(y.a-st.a)<(long long)(y.b-st.b)*(x.a-st.a);
}

void add(int u,int v){
    nxt[++en]=h[u];h[u]=en;vet[en]=v;
}

void dfs(int u){
    siz[u]=1;
    for (int e=h[u];e;e=nxt[e]){
        int v=vet[e];
        if (!d[v]){
            d[v]=d[u]+1;
            fa[v]=u;
            dfs(v);
            siz[u]+=siz[v];
        }
    }
}

void solve(int u,vector<Point> vec){
    num[vec[0].c]=u;
    st=vec[0];
    sort(vec.begin()+1,vec.end(),cmp2);
    vector <Point> tmp;int now=1;
    for (int e=h[u];e;e=nxt[e]){
        int v=vet[e];
        tmp.clear();
        if (v!=fa[u]){
            while (tmp.size()<siz[v]){tmp.push_back(vec[now]);now++;}
            solve(v,tmp);
        }
    }
}

int main(){
    scanf("%d",&n);
    for (int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for (int i=1;i<=n;i++)scanf("%d%d",&P[i].a,&P[i].b),P[i].c=i;
    sort(P+1,P+1+n,cmp1);d[1]=1;dfs(1);
    for (int i=1;i<=n;i++) vec.push_back(P[i]);
    solve(1,vec);
    for (int i=1;i<=n;i++)printf("%d ",num[i]);
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <stack>
#include <bitset>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <algorithm>
using namespace std;
#define clr(a,b) memset(a,b,sizeof(a))
#define pb(a) push_back(a)
#define fir first
#define se second
#define LL long long
typedef pair<int,int> pii;
typedef pair<LL,int> pli;
typedef pair<LL,LL> pll;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5+5;
LL mod = 1e9+7;
double eps = 0.00000001;
double PI = acos(-1);

struct point {
    int x,y,id;
	point(){}
    point(int _x,int _y){
        x=_x,y=_y;
    }
};
point con[1505];
int cnt[1505],ans[1505],vis[1505],now;
vector<int> g[1505];

LL cross(const point &p1, const point &p2, const point &q1, const point &q2)
{
    return (LL)(q2.y - q1.y)*(p2.x - p1.x) - (LL)(q2.x - q1.x)*(p2.y - p1.y);
}

bool cmp(const point &a, const point &b)
{
    point origin = con[now];
    return cross(origin,b,origin,a) < 0;
}

void dfs(int u,int fa) {
	cnt[u] = 1;
	for(int i = 0;i < g[u].size();i++) {
		int v = g[u][i];
		if(v == fa) continue;
		dfs(v,u);
		cnt[u] += cnt[v];
	}
}

void dfs1(int id,int l,int r) {
	//printf("%d--\n",id);
	int v = inf,pos;
	for(int i = l;i <= r;i++) {
		if(con[i].x < v) v = con[i].x,pos = i;
	}
	swap(con[l],con[pos]);
	now = l;
	ans[con[now].id] = id,vis[id] = 1;
	if(l == r) return ;
	sort(con+l+1,con+r+1,cmp);
	pos = l;
	for(int i = 0;i < g[id].size();i++) {
		int v = g[id][i];
		if(vis[v]) continue;
		dfs1(v,pos+1,pos+cnt[v]);
		pos += cnt[v];
	}
}

int main() {
	int n;
	cin>>n;
	clr(cnt,0);
	for(int i = 1;i < n;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		g[u].pb(v);
		g[v].pb(u);
	}
	for(int i = 1;i <= n;i++) {
		scanf("%d%d",&con[i].x,&con[i].y);
		con[i].id = i;
	}
	dfs(1,0);
	dfs1(1,1,n);
	for(int i = 1;i <= n;i++) printf("%d ",ans[i]);
	cout<<endl;
}


#include <iostream>
#include <vector>
#include <queue>
#include<algorithm>
using namespace std;
vector <int > path[1505];
vector <int> tree[1505];
int w[1505];
queue <int >q;
int n;
struct point{
    int x,y,i,ans;
}p[1505];
bool cmpx(struct point A,struct point B)
{
    if(A.x!=B.x) return A.x<B.x;
    return A.y<B.y;
}
struct point o;
long long product(struct point A,struct point B,struct point o)
{
    return ((long long)A.x-o.x)*(B.y-o.y)-((long long)A.y-o.y)*(B.x-o.x);
}
bool cmp_angle(struct point A,struct point B)
{
    return product(A,B,o)>0;
}
bool cmpi(struct point A,struct point B)
{
    return A.i<B.i;
}
void input()
{
    int x,y;
    cin>>n;
    for(int i=0;i<n-1;i++)
    {
        cin>>x>>y;
        path[x].push_back(y);
        path[y].push_back(x);
    }
    for(int i=0;i<n;i++)
    {
        cin>>p[i].x>>p[i].y;
        p[i].i=i;
    }
}
void push_v(int v, bool vis[])
{
    for(int i=0;i<path[v].size();i++) if(!vis[path[v][i]])
    {
        tree[v].push_back(path[v][i]);
        q.push(path[v][i]);
        vis[path[v][i]]=1;
    }
}
void get_tree()
{
    bool vis[1505]={};
    q.push(1);
    vis[1]=1;
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        push_v(t,vis);
    }

}
void dfs_tree(int v)
{
    w[v]=1;
    for(int i=0;i<tree[v].size();i++)
    {
        dfs_tree(tree[v][i]);
        w[v]+=w[tree[v][i]];
    }
}
void divide(int v,int l,int r)
{
    /*cout<<"------------------------------"<<endl;
    cout<<v<<" "<<l<<" "<<r<<"**"<<endl;
    for(int i=l;i<=r;i++) cout<<p[i].i<<":"<<p[i].x<<" "<<p[i].y<<endl;
    cout<<endl;*/
    sort(p+l,p+r+1,cmpx);
    p[l].ans=v;
   // cout<<p[r].x<<" "<<p[r].y<<" "<<p[r].i<<" "<<v<<endl;
    if(l==r) return;
    o.x=p[l].x,o.y=p[l].y;
    sort(p+l+1,p+r+1,cmp_angle);
    /*cout<<endl;
    for(int i=l;i<r;i++) cout<<p[i].i<<":"<<p[i].x<<" "<<p[i].y<<endl;
    cout<<endl;*/
    int tl=l+1;
    for(int i=0;i<tree[v].size();i++)
    {
        int W=w[tree[v][i]];
        divide(tree[v][i],tl,tl+W-1);
        tl+=W;
    }
}
int main()
{
    input();
    sort(p,p+n,cmpx);
    get_tree();
    dfs_tree(1);
    //for(int i=1;i<=n;i++) cout<<i<<" "<<w[i]<<endl;
    divide(1,0,n-1);
    sort(p,p+n,cmpi);
    for(int i=0;i<n;i++)
    {
        if(i) cout<<" ";
        cout<<p[i].ans;
    }
    cout<<endl;
    return 0;
}


#include <iostream>
#include <set>
#include <string>
#include <vector>
#include <algorithm>
#include <bitset>
#include <cmath>
#include <ctime>

using namespace std;

#pragma comment(linker, "/stack:256000000")

#define pii pair <int, int>
#define mp make_pair
#define ll long long

const int MN = 1500 + 10;

struct point {
	ll x, y;
	int k;
	point () {};
	point (ll xx, ll yy, int kk) {
		x = xx, y = yy;
		k = kk;
	}
	static ll dist(point a, point b) {
		return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
	}
	point operator-(point &nw) const {
		point p;
		p.x = x - nw.x;
		p.y = y - nw.y;
		return p;
	}
	static ll kos(point a, point b, point c) {
		point v1 = a - b;
		point v2 = c - b;
		return v1.x * v2.y - v1.y * v2.x;
	}
};

vector <int> g[MN];

int n;

point arr[MN];

int sz[MN];

bool used[MN];

void dfs(int v) {
	used[v] = true;
	for(int i = 0; i < g[v].size(); i ++) {
		int nv = g[v][i];
		if (!used[nv]) {
			dfs(nv);
			sz[v] += (sz[nv] + 1);
		}
	}
}

point p0;

int ans[MN];

bool my(point a, point b) {
	ll k = point::kos(a, p0, b);
	return (k < 0);
}

void solve(int lf, int rg, int root) {
	used[root] = true;
	for(int i = lf; i <= rg; i ++) {
		if (arr[i].y < arr[lf].y || (arr[i].y == arr[lf].y && arr[i].x < arr[lf].x))
			swap(arr[lf], arr[i]);
	}
	p0 = arr[lf];
	sort(arr + lf + 1, arr + rg + 1, my);
	ans[ arr[lf].k ] = root + 1;
	lf ++;
	for(int i = 0; i < g[root].size(); i ++) {
		int to = g[root][i];
		if (used[to])
			continue;
		solve(lf, lf + sz[to], to); //?
		lf += (sz[to] + 1);
	}
}

int main() {
	//freopen("input.txt", "r", stdin);
	cin >> n;
	for(int i = 0; i < n - 1; i ++) {
		int x, y;
		scanf("%d%d", &x, &y);
		x --, y --;
		g[x].push_back(y);
		g[y].push_back(x);
	}
	for(int i = 0; i < n; i ++) {
		cin >> arr[i].x >> arr[i].y;
		arr[i].k = i;
	}
	dfs(0);
	fill(&used[0], &used[0] + MN, false);
	solve(0, n - 1, 0);
	for(int i = 0; i < n; i ++)
		printf("%d ", ans[i]);
	cout << endl;
	return 0;
}


#include <stdio.h>
#include <math.h>
#include <vector>
#include <algorithm>

using namespace std;

#define MAXN (1505)

const long double pi = acosl(-1);

int N;

vector <int> edge[MAXN];

int xi[MAXN];
int yi[MAXN];

int P[MAXN];

int par[MAXN]; // tree node's parent
int V[MAXN];
int tsize[MAXN]; // subtree size

int sol[MAXN];

void dfs(int id)
{
	V[id] = 1;
	tsize[id] = 1;

	int sz = edge[id].size();
	for(int i = 0; i < sz; ++i)
	{
		int a = edge[id][i];

		if(V[a] == 0)
		{
			par[a] = id;
			dfs(a);

			tsize[id] += tsize[a];
		}
	}

//	printf("node size %d : %d\n", id + 1, tsize[id]);
}

long double sang[MAXN]; // angles used for sorting

bool cmpf(int a, int b)
{
	return sang[a] < sang[b];
}

void painttree(int id, int l, int r) // id - l, children - [l + 1, r)
{
//	printf("pt %d [%d %d) : %d\n", id + 1, l, r, P[l] + 1);
	sol[P[l]] = id + 1;

	if(l + 1 < r)
	{
		int root = P[l];
		int i;

		if(1 || tsize[id] > 3) // have more than 2 children
		{
			long double minang = 100;
			long double maxang = -100;

			for(i = l + 1; i < r; ++i)
			{
				int a = P[i];
				sang[a] = atan2l(yi[a] - yi[root], xi[a] - xi[root]);

				if(minang > sang[a])
					minang = sang[a];
				if(maxang < sang[a])
					maxang = sang[a];
			}

			if(maxang > minang + pi)
			{
				for(i = l + 1; i < r; ++i)
				{
					int a = P[i];
					if(sang[a] < 0)
						sang[a] += 2.0*pi;
				}
			}

			sort(P + l + 1, P + r, cmpf);

/*
			printf("sorted for %d :", id + 1);
			for(i = l + 1; i < r; ++i)
				printf(" %d", P[i] + 1);
			putchar('\n');
//*/
		}

		int sz = edge[id].size();
		int j = l + 1;
		for(i = 0; i < sz; ++i)
		{
			int a = edge[id][i];
			if(par[a] == id)
			{
				painttree(a, j, j + tsize[a]);
				j += tsize[a];
			}
		}
	}
}

int main()
{
	int i;

	scanf("%d", &N);
	for(i = 1; i < N; ++i)
	{
		int a, b;
		scanf("%d %d", &a, &b);
		--a;
		--b;

		edge[a].push_back(b);
		edge[b].push_back(a);
	}

	dfs(0);

	int xl = 1000000001;
	int yl = 1000000001;
	int idl = 0;

	for(i = 0; i < N; ++i)
	{
		scanf("%d %d", &xi[i], &yi[i]);

		if(xl > xi[i] || (xl == xi[i] && yl > yi[i]))
		{
			xl = xi[i];
			yl = yi[i];
			idl = i;
		}

		P[i] = i;
	}

//	printf("leftmost %d\n", idl + 1);

	P[idl] = 0;
	P[0] = idl;

	painttree(0, 0, N);

	for(i = 0; i < N; ++i)
	{
		if(i)
			putchar(' ');
		printf("%d", sol[i]);
	}
	putchar('\n');

	return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 1510*2;
int n, edge, size[MAXN], ans[MAXN];
int h[MAXN], g[MAXN], next[MAXN];
struct node {
	int x, y, k;
} v[MAXN];

void ins(int a, int b) {
	next[++edge]=h[a];
	h[a]=edge;
	g[edge]=b;
}

void dfs(int x) {
	size[x] = 1;
	for (int i=h[x];i;i=next[i])
		if (size[g[i]]==0) {
			dfs(g[i]);
			size[x] += size[g[i]];
		}
}

bool cmp(const node &a, const node &b) {
	long long t = (long long)a.x*(long long)b.y -
				  (long long)a.y*(long long)b.x;
	return t>0;
}

void dfs(int root, int l, int r) {
	if ( l>r ) return;
	node x = v[l];
	int best = l;
	for (int i=l;i<=r;i++)
		if ( v[i].y < x.y ) {
			x = v[i];
			best = i;
		}
	ans[x.k] = root;
	swap(v[best], v[l]);

	if (l==r) return;
	for (int i=l+1;i<=r;i++)
		v[i].x-=v[l].x, v[i].y-=v[l].y;
	sort(v+l+1, v+r+1, cmp);

	int now = l+1;
	for (int i=h[root];i;i=next[i])
		if (size[g[i]]<size[root]) {
			dfs(g[i], now, now+size[g[i]]-1);
			now+=size[g[i]];
		}
}

int main() {
//	freopen("input.in","r",stdin);
//	freopen("output.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<n;i++) {
		int a, b; scanf("%d%d",&a,&b);
		ins(a, b);
		ins(b, a);
	}
	dfs(1);

	for (int i=1;i<=n;i++) {
		scanf("%d%d",&v[i].x,&v[i].y);
		v[i].k = i;
	}
	dfs(1, 1, n);
	for (int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	printf("\n");
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1510;
int n;
int ans[maxn];
int tot = -1, head[maxn], cnt[maxn];
struct node {
    int p, next;
} edge[maxn << 1];
inline void Add(int u, int v) {
    edge[++tot] = (node) {v, head[u]};
    head[u] = tot;
    return;
}
struct Point {
    int x, y, idx;
    inline void Read() {
        scanf("%d%d", &x, &y);
        return;
    }
    bool operator < (const Point &a) const {
        return (x != a.x) ? (x < a.x) : (y < a.y);
    }
} p[maxn];
Point Min;
bool cmp(Point a, Point b) {
    return LL(a.y - Min.y) * (b.x - Min.x) < LL(b.y - Min.y) * (a.x - Min.x);
}
void DFS(int u, int fa) {
    cnt[u] = 1;
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].p;
        if (v != fa) {
            DFS(v, u);
            cnt[u] += cnt[v];
        }
    }
    return;
}
void Divide(int u, int fa, int l, int r) {
    int idx = l;
    for (int i = l + 1; i <= r; ++i)
        if (p[i] < p[idx]) idx = i;
    swap(p[l], p[idx]);
    ans[p[l].idx] = u;
    Min = p[l];
    sort(p + l + 1, p + r + 1, cmp);
    for (int i = head[u], j = l; ~i; i = edge[i].next) {
        int v = edge[i].p;
        if (v != fa) {
            Divide(v, u, j + 1, j + cnt[v]);
            j += cnt[v];
        }
    }
    return;
}
int main() {
    scanf("%d", &n);
    memset(head, -1, sizeof(head));
    for (int i = 1; i < n; ++i) {
        int u, v;
        scanf("%d%d", &u, &v);
        Add(u, v);
        Add(v, u);
    }
    for (int i = 1; i <= n; ++i) {
        p[i].Read();
        p[i].idx = i;
    }
    DFS(1, 0);
    Divide(1, 0, 1, n);
    for (int i = 1; i <= n; ++i)
        printf("%d ", ans[i]);
    return 0;
}


/**
 *       Compiler:  gcc
 *         Author:  bdep__
 *        Created:  06/12/2012 08:59:55 PM
 ***/

#include <cstring>
#include <cstdio>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <sstream>
#include <cmath>
#include <functional>
#include <iostream>
#include <algorithm>
#define N 1510
#define M 1000010
#define S 1000100
#define eps 1e-8
#define inf 1e10
#define MOD 1000000007
#define PB push_back
#define MP make_pair
#define SZ(a) ((int)((a).size()))
#define ALL(a) (a).begin(),(a).end()
#define CLR(a,x) memset(a,x,sizeof(a))

typedef long long LL;
using namespace std;

inline int L(int i){ return i<<1; }
inline int R(int i){ return (i<<1)|1; }
inline int B(int i){ return 1<<i; }
inline int low_bit(int x){ return x&(-x); }

struct edge{ int f,t,n; }e[N<<1];
struct node{ LL x,y; int i; }no[N];
int top,list[N],cnt[N],vis[N],ret[N];

int cmp(node a,node b)
{
	return a.x*b.y-b.x*a.y>0;
}

void insert(int f,int t)
{
	e[top].f=f,e[top].t=t;
	e[top].n=list[f],list[f]=top++;
}

void dfs(int now)
{
	cnt[now]=1;
	for(int i=list[now]; i!=-1; i=e[i].n)
	{
		int to=e[i].t;
		if(cnt[to])
			continue;
		dfs(to);
		cnt[now]+=cnt[to];
	}
}

void dfs(int now,int l,int r)
{
	if(l>r)
		return;
	vis[now]=1;
	int id=-1,nl;
	LL mi=inf;
	for(int i=l; i<=r; i++)
		if(mi>no[i].y)
			mi=no[i].y,id=i;
	swap(no[id],no[l]);
	for(int i=l+1; i<=r; i++)
		no[i].y-=no[l].y,no[i].x-=no[l].x;
	sort(no+l+1,no+r+1,cmp);
	nl=l+1;
	ret[no[l].i]=now;
	for(int i=list[now]; i!=-1; i=e[i].n)
	{
		int to=e[i].t;
		if(vis[to]) continue;
		dfs(to,nl,nl+cnt[to]-1);
		nl+=cnt[to];
	}
}

int main()
{
	int n,x,y;
	while(scanf("%d",&n)!=EOF)
	{
		top=0;
		memset(cnt,0,sizeof(cnt));
		for(int i=0; i<n; i++)
			list[i]=-1;
		for(int i=0; i<n-1; i++)
		{
			scanf("%d%d",&x,&y);
			x--,y--;
			insert(x,y);
			insert(y,x);
		}
		dfs(0);
		for(int i=0; i<n; i++)
		{
			scanf("%d%d",&x,&y);
			no[i].x=x,no[i].y=y,no[i].i=i;
		}
		memset(vis,0,sizeof(vis));
		dfs(0,0,n-1);
		for(int i=0; i<n; i++)
			printf("%d ",ret[i]+1);
		puts("");
	}
	return 0;
}


#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
const int N=1501;
struct pnt{int x,y,id; double co;}a[N]; int ans[N];
vector<int> G[N]; int sz[N];
bool operator<(const pnt &a,const pnt &b){return a.co<b.co;}
void dfs(int x,int l,int r,int fa=-1){
	int Min=0;
	for(int i=l;i<=r;++i) if(a[i].x==a[Min].x?a[i].y<a[Min].y:a[i].x<a[Min].x) Min=i;
	pnt swp=a[Min];
	for(int i=Min;i>=l+1;--i) a[i]=a[i-1]; a[l]=swp; ans[a[l].id]=x;
	for(int i=l+1;i<=r;++i) a[i].co=atan((a[i].y-a[l].y)*1.0/(a[i].x-a[l].x));
	sort(a+l+1,a+r+1); int pos=l+1;
	for(int i=0;i<G[x].size();++i){
		int e=G[x][i]; if(e==fa) continue;
		dfs(e,pos,pos+sz[e]-1,x); pos=pos+sz[e];
	}
}
void dfs_sz(int x){
	sz[x]=1;
	for(int i=0;i<G[x].size();++i){
		int e=G[x][i];
		if(!sz[e]){
			dfs_sz(e); sz[x]+=sz[e];
		}
	}
}
int main(){
	int n; scanf("%d",&n); a[0].x=0x3f3f3f3f;
	for(int i=1;i<n;++i){
		int l,r; scanf("%d%d",&l,&r);
		G[l].push_back(r); G[r].push_back(l);
	}
	for(int i=1;i<=n;++i){
		scanf("%d%d",&a[i].x,&a[i].y); a[i].id=i;
	}
	dfs_sz(1); dfs(1,1,n);
	for(int i=1;i<=n;++i) printf("%d ",ans[i]); return 0;
}


/*
Well, it rains and it pours when you're out on your own
If I crash on the couch can I sleep in my clothes?
'Cause I've spent the night dancing I'm drunk, I suppose
If it looks like I'm laughing I'm really just asking to leave

This alone, you're in time for the show
You're the one that I need, I'm the one that you loathe
You can watch me corrode like a beast in repose
Cause I love all the poison and away with the boys in the band

I've really been on a bender and it shows
So why don't you blow me a kiss before she goes?

Give me a shot to remember
And you can take all the pain away from me
A kiss and I will surrender
The sharpest lives are the deadliest to lead

A light to burn all the empires
So bright the sun is ashamed to rise and be
In love with all of these vampires
So you can leave like the sane abandoned me

There's a place in the dark where the animals go
You can take off your skin in the cannibal glow
Juliet loves the beat and the lust it commands
Drop the dagger and lather the blood on your hands, Romeo

I've really been on a bender and it shows
So why don't you blow me a kiss before she goes?

Give me a shot to remember
And you can take all the pain away from me
A kiss and I will surrender
The sharpest lives are the deadliest to lead

A light to burn all the empires
So bright the sun is ashamed to rise and be
In love with all of these vampires
So you can leave like the sane abandoned me

Give me a shot to remember
And you can take all the pain away from me
A kiss and I will surrender
The sharpest lives are the deadliest to lead

A light to burn all the empires
So bright the sun is ashamed to rise and be
In love with all of these vampires
So you can leave like the sane abandoned me
*/

//#pragma comment(linker, "/STACK:16777216")
#include <fstream>
#include <iostream>
#include <string>
#include <complex>
#include <math.h>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <stdio.h>
#include <stack>
#include <algorithm>
#include <list>
#include <ctime>
#include <memory.h>

#define y0 sdkfaslhagaklsldk
#define y1 aasdfasdfasdf
#define yn askfhwqriuperikldjk
#define j1 assdgsdgasghsf
#define tm sdfjahlfasfh
#define lr asgasgash

#define eps 1e-11
//#define M_PI 3.141592653589793
#define bs 1000000007
#define bsize 256
#define right adsgasgadsg

using namespace std;

long n,a[300000],b[300000];
vector<long> g[20000];
vector<long > vec;
long used[30000];
long ans[300000];
long dx,dy;
vector<long> sons[300000];
long sub[300000];

void dfs(long v)
{
 used[v]=1;
 for (int i=0;i<g[v].size();i++)
 {
  long q=g[v][i];
  if (used[q])continue;
  sons[v].push_back(q);
  dfs(q);
  sub[v]+=sub[q];
 }
 sub[v]++;
}

void build(long v,vector<long> vec)
{
 long lm=0;
 for (int i=0;i<vec.size();i++)
  if (a[vec[i]]<a[vec[lm]]|(a[vec[i]]==a[vec[lm]]&&b[vec[i]]<b[vec[lm]]))
   lm=i;

 ans[vec[lm]]=v;
 vector<pair<double, long> >vv;
 for (int i=0;i<vec.size();i++)
  if (i!=lm)
  {
   dx=a[vec[i]]-a[vec[lm]];
   dy=b[vec[i]]-b[vec[lm]];
   vv.push_back(make_pair(atan2(dy+.0,dx+.0),vec[i]));
  }
 sort(vv.begin(),vv.end());
 long cur=0;

 for (int i=0;i<sons[v].size();i++)
 {
  vector<long> p;
  long q=sons[v][i];
  while (p.size()<sub[q]){p.push_back(vv[cur].second);++cur;}
  build(q,p);
 }

}

int main(){
//freopen("circular.in","r",stdin);
//freopen("circular.out","w",stdout);
//freopen("C:/input.txt","r",stdin);
//freopen("C:/output.txt","w",stdout);
ios_base::sync_with_stdio(0);
//cin.tie(0);

cin>>n;
for (int i=1;i<n;i++)
{
 long a,b;
 cin>>a>>b;
 g[a].push_back(b);
 g[b].push_back(a);
}

dfs(1);
for (int i=1;i<=n;i++)
{
 cin>>a[i]>>b[i];
 vec.push_back(i);
}

build(1,vec);

for (int i=1;i<=n;i++)
{
 if (i-1)cout<<" ";
 cout<<ans[i];
}
cout<<endl;

cin.get();cin.get();
return 0;}


#include<bits/stdc++.h>
using namespace std;
const int N = 1510;
vector<int> G[N];
struct node{
	int x,y,id;
};
bool vis[N];
int son[N];
int ans[N];
node C{(int)-1e9-100,(int)-1e9-100};
//极角排序
vector<node> pt;
bool cmp(node& a,node& b)
{
	node A{a.x-C.x,a.y-C.y};
	node B{b.x-C.x,b.y-C.y};
	return 1ll*A.x*B.y - 1LL*A.y*B.x < 0;
}
//

void dfs(int x,vector<node > pt){
	int mx = 0;
	vis[x] = true;
	for(int i= 0;i < pt.size();i ++){
		if(pt[i].x < pt[mx].x )mx = i;
	}
	ans[pt[mx].id]  = x;
	C.x = pt[mx].x,C.y = pt[mx].y;
	pt.erase(pt.begin() + mx);
	sort(pt.begin(),pt.end(),cmp);
	int bef = 0;
	for(int i= 0;i < G[x].size();i ++){
		int v = G[x][i];
		if(vis[v]) continue;
		vector<node > npt;
		npt.clear();
		for(int j = bef;j < bef+son[v];j ++){
			npt.push_back(pt[j]);
		}
		bef += son[v];
		dfs(v,npt);
	}
}
int ddfs(int x){
	vis[x] = true;
	int cnt = 1;
	for(int i = 0;i < G[x].size();i ++){
		int v= G[x][i];
		if(vis[v]) continue;
		cnt += ddfs(v);
	}
	return son[x] = cnt;
}
int main(){
	int n;
	cin >>n;
	for(int i= 1;i < n;i ++){
		int a,b;
		scanf("%d %d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	for(int i= 1;i <= n;i ++){
		int a,b;
		scanf("%d %d",&a,&b);

		pt.push_back((node){a,b});
		pt[i-1].id = i;
	}
	memset(vis,false,sizeof(vis));
	ddfs(1);
	memset(vis,false,sizeof(vis));
	dfs(1,pt);
	for(int i = 1;i <= n;i ++){
		printf("%d%c",ans[i],i==n?'\n':' ');
	}

	return 0;
}
/*
10
4 3
7 6
5 7
9 5
7 4
7 8
2 5
1 7
5 10

-10 -2
-5 -7
-9 9
8 -8
0 6
-10 -7
-2 0
7 10
8 9
6 1
*/


#include <bits/stdc++.h>
using namespace std;
const int MAX_N=1505;
const long double EPS=1e-6;
inline int sgn(double x)
{
    return std::fabs(x)<EPS?0:(x>0?1:-1);
}

struct point
{
    double x,y;
    int id;
    point(){}
    point(double x,double y):x(x),y(y)
    {
    	id=0;
    }
    inline point operator - (const point &t)
	{
        return point(x-t.x,y-t.y);
    }
    inline double operator * (const point &t) const
	{
        return x*t.y-y*t.x;
    }
    inline bool operator < (const point &t) const
	{
        return !sgn(x-t.x) ? y < t.y : x < t.x;
    }
    inline bool operator == (const point &t) const
	{
        return !sgn(x-t.x) && !sgn(y-t.y);
    }

    inline double len(){
        return std::sqrt(x*x+y*y);
    }

    inline void print(){
        printf("%f %f\n",x,y);
    }
}P[MAX_N],PP;
bool comp(point a,point b)
{
    return !sgn((a-PP)*(b-PP))?((a-PP).len()<(b-PP).len()):(a-PP)*(b-PP)>0;
}
vector<int> g[MAX_N];
int n;
int ans[MAX_N];
int siz[MAX_N];
void dfs(int v,int last)
{
	siz[v]=1;
	for(int i=0;i<g[v].size();i++)
	{
		int u=g[v][i];
		if(u==last)continue;
		dfs(u,v);
		siz[v]+=siz[u];
	}
}
int idx;
inline void DFS(int v,int last,int l,int r)
{
    std::sort(P+l,P+r+1);
    PP=P[l];
    std::sort(P+l+1,P+r+1,comp);
    ans[P[l].id]=v;
	int t=l+1;
    for(int i=0;i<g[v].size();i++)
	{
		int u=g[v][i];
        if(u==last)continue;
        DFS(u,v,t,t+siz[u]-1);
        t+=siz[u];
    }
}
int main()
{
	cin>>n;
	for(int i=1;i<n;i++)
	{
		int u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i=1;i<=n;i++)
	{
		cin>>P[i].x>>P[i].y;
		P[i].id=i;
	}
	dfs(1,0);
	DFS(1,0,1,n);
	for(int i=1;i<=n;i++)cout<<ans[i]<<" \n"[i==n];
	return 0;
}


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
LL n,tot,Now,h[3005],e[3005],b[3005],s[3005],f[3005];
struct Point
{
	LL v,p,x,y;
}p[3005];

int cmp1(const Point &a,const Point &b)
{
	LL ax=a.x-p[Now].x,ay=a.y-p[Now].y;
	LL bx=b.x-p[Now].x,by=b.y-p[Now].y;
	return (ax*by-ay*bx)>0;
}

int cmp2(const Point &a,const Point &b)
{
	return (a.p<b.p);
}

void Add(LL x,LL y)
{
	b[++tot]=y; e[tot]=h[x]; h[x]=tot;
}

void Dfs(LL x)
{
	s[x]=1;
	for (LL go=h[x];go;go=e[go])
		if (f[x]!=b[go])
			f[b[go]]=x,Dfs(b[go]),s[x]+=s[b[go]];
}

void Rec(LL x,LL l,LL r)
{
	LL pos=l;
	for (LL i=l+1;i<=r;i++) if(p[i].y<p[pos].y) pos=i;
	swap(p[pos],p[l]);
	p[l].v=x;
	pos=l+1;
	Now=l; sort(p+l+1,p+r+1,cmp1);
	for (int go=h[x];go;go=e[go])
		if (b[go]!=f[x])
		{
			Rec(b[go],pos,pos+s[b[go]]-1);
			pos+=s[b[go]];
		}
}

int main()
{
	cin>>n;
	LL a,b;
	for (LL i=1;i<n;i++)
	{
		cin>>a>>b;
		Add(--a,--b); Add(b,a);
	}
	Dfs(0);
	for (LL i=0;i<n;i++)
		cin>>p[i].x>>p[i].y,p[i].p=i;
	Rec(0,0,n-1);
	sort(p,p+n,cmp2);
	for (LL i=0;i<n;i++)
		cout<<p[i].v+1<<' ';
	return 0;
}


#pragma GCC optimize("O2")
#include<bits/stdc++.h>
#define int long long
#define N 3000
using namespace std;
struct Point
{
    int x,y;int id;
    Point(){}
    Point(double _x,double _y){x=_x,y=_y;}
}now,p[N];
typedef Point Vector ;
Vector operator - (Point a,Point b){return Point(a.x-b.x,a.y-b.y);}
double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
int book[N],ans[N],n,sz[N];
vector<int> g[N];
bool cmp(Point a,Point b)
{
	return Cross(a-now,b-now)>0;
}

void dfs(int x,int fa)
{
	sz[x]=1;
	for(int i=0,v;i<g[x].size();i++) if((v=g[x][i])!=fa)
		dfs(v,x),sz[x]+=sz[v];
}
void solve(int x,int l,int r)
{
	book[x]=1;
	for(int i=l+1;i<=r;i++)
		if(p[i].x<p[l].x) swap(p[i],p[l]);
	ans[p[l].id]=x;
	now=p[l];sort(p+l+1,p+r+1,cmp);
	for(int i=0,v;i<g[x].size();i++)
	{
		if(book[v=g[x][i]]) continue;
		solve(v,l+1,l+sz[v]);
		l+=sz[v];
	}
}

main()
{
    cin>>n;
    for(int i=1;i<n;i++)
    {
		int u,v;
		scanf("%lld%lld",&u,&v);
		g[u].push_back(v),g[v].push_back(u);
	}
	dfs(1,-1);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&p[i].x,&p[i].y),p[i].id=i;
	solve(1,1,n);
	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    return 0;
}


#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;

#define maxn 1555

struct Point{
    long long x,y;
    int idx;
}point[maxn];

int n;
vector<int>g[maxn];
int sum[maxn];
int k;

long long xmulti(Point a,Point b,Point c){  //ab*ac
    return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}

bool cmp(Point a,Point b){
    return xmulti(point[k],a,b)>0;
}

void dfs(int x,int pre){

    sum[x]=1;
    for(int i=0;i<g[x].size();i++)
    {
        if(g[x][i]==pre) continue;
        dfs(g[x][i],x);
        sum[x]+=sum[g[x][i]];
    }
}

int ans[maxn];

void solve(int rt,int pre,int l,int r){

    int id=l;
    for(int i=l;i<=r;i++){

        if(point[i].x<point[id].x||(point[i].x==point[id].x&&point[i].y<point[id].y)) id=i;
    }

    if(l!=id) swap(point[l],point[id]);

    ans[point[l].idx]=rt;
    k=l;
    int t=l;
    sort(point+l+1,point+r+1,cmp);

    for(int i=0;i<g[rt].size();i++){

        int v=g[rt][i];
        if(v==pre) continue;

        solve(v,rt,t+1,t+sum[v]);
        t+=sum[v];
    }

}

int main()
{

    cin>>n;
    for(int i=0;i<n-1;i++){
        int a,b;
        cin>>a>>b;
        g[a].push_back(b);
        g[b].push_back(a);
    }

    for(int i=0;i<n;i++){

      cin>>point[i].x>>point[i].y;
       point[i].idx=i;
    }

    dfs(1,-1);
    solve(1,-1,0,n-1);

    for(int i=0;i<n;i++) {
        if(i) cout<<" ";
        cout<<ans[i];
    }
    cout<<endl;
}


#include<cstdio>
#include<bits/stdc++.h>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int Mx=1555;
int n,X,Y;
int fir[Mx],nex[Mx<<1],to[Mx<<1],tot;
void addEdge(int x,int y){
    nex[++tot]=fir[x];fir[x]=tot;to[tot]=y;
}
int ans[Mx],top,si[Mx];
struct Node{
    int x,y,id;
}node[Mx];
bool cmp(Node a,Node b){return 1ll *(a.x-X)*(b.y-Y)<1ll *(b.x-X)*(a.y-Y);}
void dfs(int x,int f){
    si[x]++;
    for(int i=fir[x];i;i=nex[i]){
        int v=to[i];
        if(v==f)continue;
        dfs(v,x);
        si[x]+=si[v];
    }
}
void getXY(int l,int r){
    if(l==r)return;
    X=1e9;
    int id=l;
    for(int i=l;i<=r;i++)if(node[i].x<X)X=node[i].x,Y=node[i].y,id=i;
    swap(node[id],node[l]);
    sort(node+l+1,node+r+1,cmp);
}
void getAns(int l,  int r, int x,int f){
    getXY(l, r);
   // cout<<l<<" "<<r<<" "<<x<<endl;
    ans[node[l].id]=x;
    int now = l + 1;
    for(int i=fir[x];i;i=nex[i]){
        int v=to[i];
        if(v==f)continue;
        getAns(now, now + si[v] - 1, v, x);
        now = now + si[v];
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%d%d",&X,&Y);
        addEdge(X,Y);
        addEdge(Y,X);
    }
    for(int i=1;i<=n;i++){
        scanf("%d%d",&node[i].x,&node[i].y);
        node[i].id=i;
    }
    dfs(1,0);
    getAns(1, n, 1, 0);
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
}
/*
5
1 2
2 3
1 4
4 5
-4 3
2 3
-1 1
0 -1
1 5
*/


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <queue>

#define pause cout << " press any key to continue...",  cin >> chh
#define file_r(x) freopen(x,  "r",  stdin)
#define file_w(x) freopen(x,  "w",  stdout)

using namespace std;
int chh;

typedef long long LL;

const int N = 1505, M = N * 2, INF = ~0U >> 2;

struct Point {
    int x, y, h;
} p[N];

struct NODE {
    int v, next;
} edge[M];

int n, e, cp;
int ans[N], size[N], head[N];
bool ab[N];

LL cross(int x1, int y1, int x2, int y2) {
    return (LL) x1 * y2 - (LL) x2 * y1;
}

bool cmp(const Point &arg0, const Point &arg1) {
    return cross(arg0.x - p[cp].x, arg0.y - p[cp].y, arg1.x - p[cp].x, arg1.y - p[cp].y) < 0;
}

void init() {
    e = 0;
    fill(head + 1, head + n + 1, -1);
}

void add_edge(int u, int v) {
    edge[e].v = v, edge[e].next = head[u], head[u] = e++;
}

void dfs(int u, int fa) {
    int i, v;
    size[u] = 1;
    for (i = head[u]; i != -1; i = edge[i].next) {
        v = edge[i].v;
        if (v == fa) continue;
        dfs(v, u);
        size[u] += size[v];
    }
}

void solve(int id, int l, int r) {
    int i, j, v = INF;
    for (i = l; i <= r; i++)
        if (p[i].x < v) v = p[i].x, j = i;
    swap(p[l], p[j]);
    cp = l;
    ans[p[cp].h] = id, ab[id] = 1;
    if (l == r) return;
    sort(p + l + 1, p + r + 1, cmp);
    j = l;
    for (i = head[id]; i != -1; i = edge[i].next) {
        v = edge[i].v;
        if (ab[v]) continue;
        solve(v, j + 1, j + size[v]);
        j += size[v];
    }
}

int main() {
    int i, j, u, v;
    while (scanf("%d", &n) != EOF) {
        init();
        for (i = 1; i < n; i++) {
            scanf("%d %d", &u, &v);
            add_edge(u, v), add_edge(v, u);
        }
        for (i = 1; i <= n; i++) {
            scanf("%d %d", &p[i].x, &p[i].y);
            p[i].h = i;
        }
        dfs(1, -1);
        //cout << "PPPP"; pause;
        //for (i = 1; i <= n; i++) cout << size[i] << endl; pause;
        fill(ab + 1, ab + n + 1, 0);
        solve(1, 1, n);
        for (i = 1; i < n; i++) printf("%d ", ans[i]);
        printf("%d\n", ans[n]);
    }
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct point64_t {
	int64_t x, y, num;
	point64_t() { x = 0, y = 0, num = 0; }
	point64_t(int64_t a, int64_t b, int64_t c) {
		x = a, y = b, num = c;
	}
};
struct Vector {
	int64_t x, y;
	Vector() { x = 0, y = 0; }
	Vector(point64_t a, point64_t b) { x = b.x - a.x, y = b.y - a.y; }
};
int64_t skal(Vector a, Vector b) {
	return (a.x * b.x + a.y * b.y);
}
int64_t vect(Vector a, Vector b) {
	return (a.x * b.y - a.y * b.x);
}
point64_t minp;
bool cmp(point64_t& a, point64_t& b) {
	Vector i(minp, a);
	Vector j(minp, b);
	if (vect(i, j) == 0) {
		return skal(i, i) < skal(j, j);
	}
	return vect(i, j) > 0;
}
vector<vector<int64_t>> g;
vector<int64_t> sz;
vector<int64_t> par;
void dfs(int64_t v, int64_t p) {
	sz[v] = 1;
	par[v] = p;
	for (auto u : g[v]) {
		if (u != p) {
			dfs(u, v);
			sz[v] += sz[u];
		}
	}
}
vector<int64_t> sootv;
void solve(int64_t root, vector<point64_t> a) {
	int64_t n = a.size();
	vector<pair<pair<int64_t, int64_t>, int64_t>> help(n);
	for (int64_t i = 0; i < n; ++i) {
		help[i] = { {a[i].x,a[i].y},i };
	}
	sort(help.begin(), help.end());
	minp = a[help[0].second];
	vector<point64_t> b;
	for (int64_t i = 0; i < n; ++i) {
		if (i != help[0].second) b.push_back(a[i]);
	}
	sort(b.begin(), b.end(), cmp);
	sootv[minp.num] = root;
	for (auto u : g[root]) {
		if (u == par[root]) continue;
		vector<point64_t> c;
		for (int64_t j = 0; j < sz[u]; ++j) {
			c.push_back(b[b.size() - 1]);
			b.pop_back();
		}
		solve(u, c);
	}
}
int main() {
	int64_t n;
	cin >> n;
	g.resize(n);
	sz.resize(n);
	par.resize(n);
	sootv.resize(n);
	for (int64_t i = 0; i < n - 1; ++i) {
		int64_t u, v;
		cin >> u >> v;
		--u, --v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(0, -1);
	vector<point64_t> a(n);
	for (int64_t i = 0; i < n; ++i) {
		cin >> a[i].x >> a[i].y;
		a[i].num = i;
	}
	solve(0, a);
	for (int64_t i = 0; i < n; ++i) cout << sootv[i] + 1 << ' ';
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 1500 + 10;
int n,x,y;
struct node {
	int xx,yy,id;
	bool operator < (const node &a) const {
		if(xx-x>=0 && a.xx-x<=0) return 1;
		if(xx-x<=0 && a.xx-x>=0) return 0;
		return (yy-y)*(ll)(a.xx-x)<(a.yy-y)*(ll)(xx-x);
	}
}p[M];

vector<int> g[M];
int sz[M];
int ans[M];

void dfs (int o,int u) {
	sz[u] = 1;
    for (int &v : g[u]) if (v!=o) {
		dfs (u, v);
		sz[u] += sz[v];
    }
}

void dfs2 (int o,int u,int l,int r) {
	if (sz[u]==1) {
		ans[p[l].id] = u;
		return;
	}
	int id=l;
    for (int i=l+1; i<r; ++i) {
		if (p[i].xx < p[id].xx) {
			id = i;
		}
    }
    swap(p[id], p[l]);
    ans[p[l].id] = u;
    x=p[l].xx, y=p[l].yy;
    sort (p+l+1, p+r);
    int sum = l+1;
    for (int &v : g[u]) if (v!=o) {
		dfs2 (u, v, sum, sum+sz[v]);
		sum += sz[v];
    }
}

int main () {
	scanf ("%d", &n);
	for (int i=1,u,v; i<n; ++i) {
		scanf ("%d%d", &u,&v);
		g[u].emplace_back(v);
		g[v].emplace_back(u);
	}
	for (int i=0; i<n; ++i) {
        scanf ("%d%d", &p[i].xx, &p[i].yy);
        p[i].id = i;
	}
	dfs (1, 1);
	dfs2 (1, 1, 0, n);
	for (int i=0; i<n; ++i) {
		printf ("%d%c", ans[i], " \n"[i==n-1]);
	}
	return 0;
}


#include <limits>
#include <list>
#include <stack>
#include <algorithm>
#include <iostream>
#include <vector>
#include <utility>

using namespace std;
typedef long long ll;
typedef vector<int> vi;
struct point{
    point(){};
    point(ll x_, ll y_, int i_):x(x_),y(y_),idx(i_){};
    ll x;
    ll y;
    int idx;
};

//const point nilpair = make_pair(numeric_limits<ll>::min(),numeric_limits<ll>::min());
bool cmpr(const point& l, const point& r){
    ll s = l.x * r.y - l.y * r.x;
    return s > 0;
}
void place(int vert, vector<point>& p, int l, int r, vi& a,  vector<vi>& c, vi& sz){
    int root = l;
    if (l > r) return;
    for (int i = l; i < r; ++i){
        if (p[i].y > p[root].y){
            root = i;
        }
    }
    a[p[root].idx] = vert + 1;
    swap(p[root],p[l]);
    if (l == r) return;
    for(int i = l+1; i < r; ++i){
        p[i].x -= p[l].x;
        p[i].y -= p[l].y;
    }
    sort(p.begin() + l + 1, p.begin() + r,cmpr);
    int pos = l+1;
    for(int i = 0; i < c[vert].size(); ++i){
        if (sz[c[vert][i]] < sz[vert]){
            place(c[vert][i], p, pos, pos + sz[c[vert][i]],a,c,sz);
            pos += sz[c[vert][i]];
        }
    }
}
int main(void)
{
    int n;
    cin >> n;
    vector<int> v(n,0);
    vector<int>  sz(n,0);
    vector<vector<int> > c(n);
    vector<point> pts(n);
    int i = n-1;
    while(i--){
        int s, d;
        cin >> s >> d;
        c[s-1].push_back(d-1);
        c[d-1].push_back(s-1);
    }
    stack<int> s;
    s.push(0);
    while(!s.empty()){
        int vr = s.top();
        if (0 == v[vr]){
            v[vr] = 1;
            sz[vr] = 1;
        }
        for(int i = 0; i < c[vr].size(); ++i){
            if (0 == v[c[vr][i]]){
                s.push(c[vr][i]);
                break;
            }
        }
        if (vr == s.top()){
            v[vr] = 2;
            s.pop();
            for(int i = 0; i < c[vr].size(); ++i){
                if (2 == v[c[vr][i]]) sz[vr] += sz[c[vr][i]];
            }
        }
    }
    for(int i = 0; i < n; i++){
        ll x, y;
        cin >> x >> y;
        pts[i] = point(x, y, i);
    }
    place(0, pts, 0, pts.size(), v, c, sz);
    for(int i = 0; i < n; ++i){
        cout << v[i] <<' ';
    }
    cout << endl;
    return 0;
}


#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
struct Point {
	double x, y;
	int num;
	Point() {}
	Point(double _x, double _y, int _num): x(_x), y(_y), num(_num) {}
	void read() {
		scanf("%lf%lf", &x, &y);
	}
	double operator * (const Point &a) const {
		return x * a.y - a.x * y;
	}
	Point operator - (const Point &a) const {
		return Point(x - a.x, y - a.y, num);
	}
	bool operator < (const Point &a) const {
		return y < a.y || y == a.y && x < a.x;
	}
	bool operator == (const Point &a) const {
		return x == a.x && y == a.y;
	}
} a[2000], s;
int sum = 0, cnt = 0, n, ans[2000], sz[2000];
int des[4000], nxt[4000], fst[2000];
int c[2000], nxtc[2000], fstc[2000];
bool vis[2000];

void add(int x, int y) {
	des[++sum] = y, nxt[sum] = fst[x], fst[x] = sum;
}
void add2(int x, int y) {
	c[++cnt] = y, nxtc[cnt] = fstc[x], fstc[x] = cnt;
}
void tree(int x) {
	vis[x] = 1;
	sz[x] = 1;
	for (int i = fst[x]; i; i = nxt[i])
		if (!vis[des[i]]) tree(des[i]), add2(x, des[i]), sz[x] += sz[des[i]];
}
double cross(Point a, Point b, Point c) {
	return (a - c) * (b - c);
}
bool cmp(Point i, Point j) {
	if (i == s) return 1;
	if (j == s) return 0;
	double y = cross(i, j, s);
	if (y < 0) return 0;
	return 1;
}
void solve(vector<Point>b, int fa) {
	s = b[0];
	for (int i = 1; i < b.size(); ++i) if (b[i] < s) s = b[i];
	sort(b.begin(), b.end(), cmp);
	int l = 1;
	ans[s.num] = fa;
	for (int i = fstc[fa]; i; i = nxtc[i]) {
		int k = c[i];
		vector<Point>m;
		for (int j = 1; j <= sz[k]; ++j) m.push_back(b[l]), l++;
		solve(m, k);
	}
}
int main() {
	scanf("%d", &n);
	for (int i = 1; i < n; ++i) {
		int x, y;
		scanf("%d%d", &x, &y);
		add(x, y), add(y, x);
	}
	memset(vis, 0, sizeof vis);
	tree(1);
	vector<Point>b;
	for (int i = 1; i <= n; ++i) a[i].read(), a[i].num = i, b.push_back(a[i]);
	solve(b, 1);
	for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int maxn=1520;
int n,X,Y;
struct PO {
	int x,y,d;
	bool operator<(const PO &o) const {
		if(x-X>=0&&o.x-X<=0) return 1;
		if(x-X<=0&&o.x-X>=0) return 0;
		return (y-Y)*(long long)(o.x-X)<(o.y-Y)*(long long)(x-X);
	}
}p[maxn];
vector<int> g[maxn];
bool vis[maxn];
int sz[maxn],o[maxn];
int dfs(int u)
{
	vis[u]=true;
	sz[u]=1;
	int ret=0;
	for(int i=0,j=g[u].size();i<j;i++)	 {
		int v=g[u][i];
		if(vis[v])
			continue;
		ret+=dfs(v);
	}
	sz[u]+=ret;
	return sz[u];
}
void calc(int u,int l,int r)
{
	vis[u]=true;
	int t=l;
	for(int i=l+1;i<=r;i++)
		if((p[i].y<p[t].y)||(p[t].y==p[i].y&&p[i].x<p[t].x))
			t=i;
	if(t!=l)
		swap(p[l],p[t]);
	o[p[l].d]=u;
	X=p[l].x;
	Y=p[l].y;
	sort(p+l+1,p+r+1);
	int pos=l+1;
	for(int i=0,j=g[u].size();i<j;i++) {
		int v=g[u][i];
		if(vis[v])
			continue;
		calc(v,pos,pos+sz[v]-1);
		pos+=sz[v];
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n-1;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		g[x].push_back(y);
		g[y].push_back(x);
	}
	for(int i=1;i<=n;i++) {
		int x,y;
		scanf("%d%d",&x,&y);
		p[i]=(PO){x,y,i};
	}
	dfs(1);
	memset(vis,0,sizeof(vis));
	calc(1,1,n);
	for(int i=1;i<=n;i++)
		printf("%d ",o[i]);
	putchar(10);
	return 0;
}


#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <fstream>
#include <sstream>
#include <stack>
#include <queue>
#include <utility>
#include <cmath>
#include <algorithm>
#include <limits.h>
#include <iterator>

using namespace std;

#define pb push_back
#define SIZE(x) (int)x.size()

#define F first
#define S second
#define MP make_pair
typedef pair<int,int> PII;
typedef pair<PII,int> PIII;

int n;
bool adj[1501][1501];
int vtx[1501];
vector<bool> chk;
vector <PIII> points;
vector <PII> res;

int dfs(int node)
{
    int cnt = 0;
    chk[node] = true;
    for(int i = 1;i <= n;++i)
        if(!chk[i] && adj[node][i])
            cnt += dfs(i);
    vtx[node] = cnt+1;
    return vtx[node];
}

void go(int root, vector<PIII> ps)
{
    int min_y = INT_MAX, min_i = -1;
    for(int i = 1;i <= ps.size()-1;++i) if(ps[i].F.S < min_y) {min_y = ps[i].F.S; min_i = i;}
    res.push_back(MP(ps[min_i].S,root));
    vector<pair<long double,int> > tps(1);
    for(int i = 1;i <= ps.size()-1;++i) if(i != min_i) tps.push_back(MP(atan2l(ps[i].first.first-ps[min_i].first.first,ps[i].first.second-ps[min_i].first.second),i));
    sort(tps.begin()+1,tps.end());
    int s = 1;
    for(int i = 1;i <= n;++i) if(adj[root][i]) {
        vector<PIII> nps(1);
        while(nps.size() < vtx[i]+1) {
            nps.push_back(ps[tps[s].S]);
            ++s;
        }
        adj[i][root] = false;
        go(i,nps);
    }
}

int main()
{
#ifdef LOCAL
	freopen("in.txt", "r", stdin);
#endif
    cin >> n;
    for(int i;i<n+1;++i) for(int j;j<n+1;++j) adj[i][j] = false;
    points.resize(n+1);
    chk.resize(n+1,false);
    memset(vtx,0,sizeof(vtx));

    for(int i;i<n-1;++i) {
        int a, b;
        cin >> a >> b;
        adj[a][b] = adj[b][a] = true;
    }

    for(int i;i<n;++i) {
        int x, y;
        cin >> x >> y;
        points[i+1] = MP(MP(x,y),i+1);
    }

    dfs(1);

    sort(points.begin()+1,points.end());
    for(int i;i<n+1;++i) chk[i] = false;

    go(1,points);

    sort(res.begin(),res.end());

    for(int i = 0;i < res.size();++i) cout << res[i].second << " ";

    return 0;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 1510*2;
int n, edge, size[MAXN], ans[MAXN];
int h[MAXN], g[MAXN], next[MAXN];
struct node {
	int x, y, k;
} v[MAXN];

void ins(int a, int b) {
	next[++edge]=h[a];
	h[a]=edge;
	g[edge]=b;
}

void dfs(int x) {
	size[x] = 1;
	for (int i=h[x];i;i=next[i])
		if (size[g[i]]==0) {
			dfs(g[i]);
			size[x] += size[g[i]];
		}
}

bool cmp(const node &a, const node &b) {
	long long t = (long long)a.x*(long long)b.y -
				  (long long)a.y*(long long)b.x;
	return t>0;
}

void dfs(int root, int l, int r) {
	if ( l>r ) return;
	node x = v[l];
	int best = l;
	for (int i=l;i<=r;i++)
		if ( v[i].y < x.y ) {
			x = v[i];
			best = i;
		}
	ans[x.k] = root;
	swap(v[best], v[l]);

	if (l==r) return;
	for (int i=l+1;i<=r;i++)
		v[i].x-=v[l].x, v[i].y-=v[l].y;
	sort(v+l+1, v+r+1, cmp);

	int now = l+1;
	for (int i=h[root];i;i=next[i])
		if (size[g[i]]<size[root]) {
			dfs(g[i], now, now+size[g[i]]-1);
			now+=size[g[i]];
		}
}

int main() {
//	freopen("input.in","r",stdin);
//	freopen("output.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;i<n;i++) {
		int a, b; scanf("%d%d",&a,&b);
		ins(a, b);
		ins(b, a);
	}
	dfs(1);

	for (int i=1;i<=n;i++) {
		scanf("%d%d",&v[i].x,&v[i].y);
		v[i].k = i;
	}
	dfs(1, 1, n);
	for (int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	printf("\n");
}


#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=(a),i##_end_=(b);i<=i##_end_;i++)
#define DOR(i,a,b) for(int i=(a),i##_end_=(b);i>=i##_end_;i--)
#define ll long long
#define M 1505
using namespace std;

int n;
int sz[M];
int Ans[M];
int Id[M];

vector<int>G[M];

struct node{
	int x,y;
	int id;

	bool operator <(const node &a)const{
		return x<a.x;
	}

}A[M],tmp;

bool cmp(node a,node b){
	return 1ll*(a.x-tmp.x)*(b.y-tmp.y)>1ll*(b.x-tmp.x)*(a.y-tmp.y);
}

void dfs(int x,int f){
	sz[x]=1;
	for(int i=0;i<(int)G[x].size();i++){
		if(G[x][i]==f){
			Id[x]=i;
			continue;
		}
		dfs(G[x][i],x);
		sz[x]+=sz[G[x][i]];
	}
}

void solve(int L,int R,int f){
	sort(A+L,A+R+1);
	Ans[A[L].id]=f;
	if(L==R)return;
	tmp=A[L];
	sort(A+L+1,A+R+1,cmp);
	int st=L+1;
	int tot=0;
	if(tot==Id[f])tot++;
	int size=0;
	FOR(i,L+1,R){
		size++;
		if(size==sz[G[f][tot]]){
			solve(st,i,G[f][tot]);
			st=i+1;
			tot++;
			if(tot==Id[f])tot++;
			size=0;
		}
	}
}

int main(){
	scanf("%d",&n);
	FOR(i,1,n-1){
		int a,b;
		scanf("%d%d",&a,&b);
		G[a].push_back(b);
		G[b].push_back(a);
	}
	memset(Id,-1,sizeof(Id));
	FOR(i,1,n){
		scanf("%d%d",&A[i].x,&A[i].y);
		A[i].id=i;
	}
	dfs(1,0);
	solve(1,n,1);
	FOR(i,1,n)printf("%d ",Ans[i]);
	puts("");
	return 0;
}


#include <bits/stdc++.h>
#include <unistd.h>
#define inf 1000000007LL
#define INF 1000000000000000007LL
#define endl cout<<'\n'
#define endr cerr<<'\n'
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define st first
#define nd second
#define mxe max_element
#define mne min_element
#define bit(i) (1LL<<(i))
#define log(x) (63-__builtin_clzll(x))
#define ll long long
#define pii pair<int,int>
#define pdd pair<double,double>
#define vi vector<int>
#define vd vector<double>
#define vll vector<long long>
#define vpii vector< pair<int,int> >
#define sz(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define rep(i, n) for(int i=0; i<(n); ++i)
#define rep1(i, n) for(int i=1; i<=(n); ++i)
#define pv(x) cerr<<#x<<": "<<(x)<<'\n'
#define ps(x) cerr<<#x<<": ";for(auto q:(x)){cerr<<q<<" ";}cerr<<'\n'
#define pa(x, xs) cerr<<#x<<": ";for(int q=0; q<=(xs); ++q){cerr<<x[q]<<" ";}cerr<<'\n'
#define pal(x, xs) cerr<<'\n'<<#x<<":\n";for(int q=0; q<=(xs); ++q){cerr<<q<<": "<<x[q]<<'\n';}cerr<<'\n'
#define ppii(x, xs) cerr<<'\n'<<#x<<":\n";for(int q=0; q<=(xs); ++q){cerr<<q<<": "<<x[q].first<<" "<<x[q].second<<'\n';}cerr<<'\n'
#define pm(x, xn, xm) cerr<<'\n'<<#x<<":\n";for(int qa=0; qa<=(xn); ++qa){for(int qb=0; qb<=(xm); ++qb){cerr<<setw(5)<<x[qa][qb]<<" ";}cerr<<'\n';}cerr<<'\n'
using namespace std;
#define N 2007
#define int long long
//#define double long double
//#define cerr if(0)cout

int n, x[N], y[N], par[N], sub[N], ans[N];
vi g[N], allPoints;

void DFStree(int v)
{
  sub[v] = 1;
  for (auto u : g[v])
  {
    if (u == par[v]) continue;
    par[u] = v;
    DFStree(u);
    sub[v] += sub[u];
  }
}

void build(int vRoot, vi points)
{
  int pRoot = points[0];
  for (auto p : points)
  {
    if (y[p] < y[pRoot] || (y[p] == y[pRoot] && x[p] < x[pRoot])) pRoot = p;
  }
  ans[pRoot] = vRoot;

  vector< pair<double, int> > sorted;
  for (auto p : points)
  {
    if (p == pRoot) continue;
    int xDif = x[p] - x[pRoot], yDif = y[p] - y[pRoot];
    sorted.eb(atan2(yDif+.0, xDif+.0), p);
  }

  sort(all(sorted));

  for (auto u : g[vRoot])
  {
    if (u == par[vRoot]) continue;
    vi forSubtree;
    while (sz(forSubtree) < sub[u])
    {
      forSubtree.pb(sorted.back().nd); sorted.pop_back();
    }
    build(u, forSubtree);
  }
}

void solve()
{
  cin>>n;
  rep1(i, n-1)
  {
    int a, b; cin>>a>>b;
    g[a].pb(b);
    g[b].pb(a);
  }

  DFStree(1);

  rep1(i, n) cin>>x[i]>>y[i], allPoints.pb(i);

  build(1, allPoints);

  rep1(i, n) cout<<ans[i]<<" ";
}

int32_t main()
{
ios_base::sync_with_stdio(0);
cin.tie(NULL);
//cout<<fixed<<setprecision(10);

  solve();

return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <cctype>
#include <cassert>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <bitset>
#include <algorithm>
#include <numeric>
#include <complex>

#define D(x) cerr << #x << " = " << x << endl
#define REP(i,a,n) for(int i=(a); i<(int)(n); i++)
#define FOREACH(it,v) for(typeof((v).begin()) it=(v).begin(); it!=(v).end(); ++it)
#define ALL(v) (v).begin(), (v).end()
#define mp(x,y) make_pair(x, y)
#define pb(x) push_back(x)

typedef long long int64;

const int INF = (int)(1e9);
const int64 INFLL = (int64)(1e18);
const double EPS = 1e-13;

using namespace std;

typedef vector<int> vi;

const int MAXN = 1500 + 10;

int X[MAXN], Y[MAXN], ans[MAXN], size[MAXN];
vi G[MAXN];

int bfs(int v, int parent) {
    size[v] = 1;
    REP(i, 0, G[v].size()) {
        int u = G[v][i];
        if(u != parent) {
            size[v] += bfs(u, v);
        }
    }
    return size[v];
}

bool cmp(int i, int j) {
    return (int64)X[i] * Y[j] - (int64)X[j] * Y[i] < 0;
}

void go(vi p, int v, int parent) {
    int min_i = 0;
    REP(i, 0, p.size()) {
        if (mp(X[p[i]], Y[p[i]]) < mp(X[p[min_i]], Y[p[min_i]]))
            min_i = i;
    }

    swap(p[0], p[min_i]);

    REP(i, 0, p.size()) {
        if(i != 0) {
            X[p[i]] -= X[p[0]];
            Y[p[i]] -= Y[p[0]];
        }
    }

    sort(p.begin() + 1, p.end(), cmp);

    REP(i, 0, p.size()) {
        if(i != 0) {
            X[p[i]] += X[p[0]];
            Y[p[i]] += Y[p[0]];
        }
    }

    int pos = 1, u;
    ans[p[0]] = v;

    REP(i, 0, G[v].size()) {
        u = G[v][i];
        if(u != parent) {
            vi q;
            REP(i, 0, size[u]) {
                q.pb(p[pos++]);
            }
            go(q, u, v);
        }
    }
}

int main() {
    ios_base::sync_with_stdio(false);
    int n, u, v;
    cin >> n;

    REP(i, 0, n-1) {
        cin >> u >> v;
        u--, v--;
        G[u].pb(v); G[v].pb(u);
    }

    vi p;
    REP(i, 0, n) {
        cin >> X[i] >> Y[i];
        p.pb(i);
    }

    bfs(0, -1);
    go(p, 0, -1);

    REP(i, 0, n) {
        if(i) cout << ' ';
        cout << (ans[i] + 1);
    }
    cout << endl;
}


#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int MAXN = 1510*2;
int n, edge, size[MAXN], ans[MAXN];
int h[MAXN], g[MAXN], next[MAXN];
struct node {
	int x, y, k;
} v[MAXN];

void ins(int a, int b) {
	next[++edge]=h[a];
	h[a]=edge;
	g[edge]=b;
}

void dfs(int x) {
	size[x] = 1;
	for (int i=h[x];i;i=next[i])
		if (size[g[i]]==0) {
			dfs(g[i]);
			size[x] += size[g[i]];
		}
}

bool cmp(const node &a, const node &b) {
	long long t = (long long)a.x*(long long)b.y -
				  (long long)a.y*(long long)b.x;
	return t>0;
}

void dfs(int root, int l, int r) {
	if ( l>r ) return;
	node x = v[l];
	int best = l;
	for (int i=l;i<=r;i++)
		if ( v[i].y < x.y ) {
			x = v[i];
			best = i;
		}
	ans[x.k] = root;
	swap(v[best], v[l]);

	if (l==r) return;
	for (int i=l+1;i<=r;i++)
		v[i].x-=v[l].x, v[i].y-=v[l].y;
	sort(v+l+1, v+r+1, cmp);

	int now = l+1;
	for (int i=h[root];i;i=next[i])
		if (size[g[i]]<size[root]) {
			dfs(g[i], now, now+size[g[i]]-1);
			now+=size[g[i]];
		}
}

int main() {
	scanf("%d",&n);
	for (int i=1;i<n;i++) {
		int a, b; scanf("%d%d",&a,&b);
		ins(a, b);
		ins(b, a);
	}
	dfs(1);

	for (int i=1;i<=n;i++) {
		scanf("%d%d",&v[i].x,&v[i].y);
		v[i].k = i;
	}
	dfs(1, 1, n);
	for (int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	printf("\n");
}


#include <cstdio>
#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;

struct pkt
{
    ll x, y;
    int nr;
};

int n;

void dfs(vector< vector<int> >& T, vector<int>& wlk, int akt, int oj)
{
    for (int i = 0; i < T[akt].size(); ++i)
        if (T[akt][i] != oj)
            dfs(T, wlk, T[akt][i], akt);
    if (T[akt].size() == 1 && akt != 0)
        wlk[akt] = 1;
    else
    {
        wlk[akt] = 1;
        for (int i = 0; i < T[akt].size(); ++i)
            if (T[akt][i] != oj)
                wlk[akt] += wlk[T[akt][i]];
    }
}

int Cwiartka(pkt a)
{
    if (a.x > 0 && a.y >= 0)
        return 0;
    if (a.x <= 0 && a.y > 0)
        return 1;
    if (a.x < 0 && a.y <= 0)
        return 2;
    if (a.x >= 0 && a.y < 0)
        return 3;
}

bool porownanie(pkt a, pkt b)
{
    int cwA = Cwiartka(a);
    int cwB = Cwiartka(b);
    if (cwA != cwB)
    {
        if (cwA < cwB)
            return true;
        return false;
    }
    else
    {
        ll ay = abs(a.y), ax = abs(a.x);
        ll by = abs(b.y), bx = abs(b.x);
        if (cwA == 0 || cwA == 2)
        {
            if (ay * bx < ax * by)
                return true;
            return false;
        }
        else
        {
            if (ay * bx > ax * by)
                return true;
            return false;
        }
    }
}

void Sortuj(vector<pkt>& p, pkt s)
{
    for (int i = 0; i < p.size(); ++i)
    {
        p[i].x -= s.x;
        p[i].y -= s.y;
    }
    sort(p.begin(), p.end(), porownanie);
    for (int i = 0; i < p.size(); ++i)
    {
        p[i].x += s.x;
        p[i].y += s.y;
    }
}

void Solve(vector< vector<int> >& T, vector<pkt> p, vector<int>& wlk,
           int akt, int oj, vector<int>& odp)
{
    pkt sr = {-1, -1, -1};
    int x = -1;
    for (int i = 0; i < p.size(); ++i)
    {
        if (x == -1 || p[i].y < sr.y || (p[i].y == sr.y && p[i].x < sr.x))
        {
            sr = p[i];
            x = i;
        }
    }
    vector<pkt> p2;
    for (int i = 0; i < p.size(); ++i)
        if (i != x)
            p2.push_back(p[i]);
    p = p2;
    odp[sr.nr] = akt;
    Sortuj(p, sr);
    int nr = 0;
    for (int i = 0; i < T[akt].size(); ++i)
    {
        if (T[akt][i] != oj)
        {
            vector<pkt> t;
            for (int j = nr; j <= nr + wlk[T[akt][i]] - 1; ++j)
                t.push_back(p[j]);
            Solve(T, t, wlk, T[akt][i], akt, odp);
            nr += wlk[T[akt][i]];
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n;
    vector< vector<int> > T(n);
    for (int i = 0; i < n - 1; ++i)
    {
        int a, b;
        cin >> a >> b;
        --a;
        --b;
        T[a].push_back(b);
        T[b].push_back(a);
    }
    vector<pkt> P(n);
    for (int i = 0; i < n; ++i)
    {
        cin >> P[i].x >> P[i].y;
        P[i].nr = i;
    }
    vector<int> wlk(n);
    dfs(T, wlk, 0, -1);
    vector<int> odp(n);
    Solve(T, P, wlk, 0, -1, odp);
    for (int i = 0; i < n; ++i)
        cout << odp[i] + 1 << " ";
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e3+10;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
#define fir first
#define se second
const int N = 2e3 + 7;
const double eps = 1e-8;
int n, ans[N], sz[N];
struct Pt{
	Pt(double x = 0,double y = 0, int id = 0) : x(x),y(y){}
	double x, y;
 	int id;
};
vector<int> g[N];
Pt pts[N];
inline int dcmp(double x) { return x < -eps ? -1 : x > eps; }
double det(const Pt &a,const Pt &b) { return a.x * b.y - a.y * b.x; }
Pt operator-(Pt a, Pt b) { return Pt(a.x - b.x, a.y - b.y); }
Pt operator+(Pt a, Pt b) { return Pt(a.x + b.x, a.y + b.y); }
double norm(Pt p){ return sqrt(p.x*p.x + p.y*p.y); }
double dist(Pt a,Pt b){ return norm(a-b); }
int base;
bool cmp(const Pt& a,const Pt& b){
	double t = det(a-pts[base],b-pts[base]);
	if(fabs(t) < eps) return dist(a,pts[base]) < dist(b,pts[base]);
	return t > eps;
}

void dfs1(int u, int fa){
	sz[u] = 1; for(int v : g[u]) if(v != fa) dfs1(v, u), sz[u] += sz[v];
}

void dfs2(int u, int fa, int pos, int end){
	for(int i = pos+1; i < end; ++ i){
		pii a(pts[pos].x, pts[pos].y), b(pts[i].x, pts[i].y);
		if(b < a)
			swap(pts[pos],pts[i]);
	}
	ans[pts[pos].id] = u;
	base = pos;
	sort(pts+pos+1, pts+end, cmp);
	for(int v : g[u]) if(v != fa) {
		dfs2(v, u, pos+1, pos+sz[v]+1);
		pos += sz[v];
	}
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i < n; ++ i){
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		g[v].push_back(u);
	}
	for(int i = 0; i < n; ++ i){
		double x, y;
		scanf("%lf%lf", &pts[i].x, &pts[i].y); pts[i].id = i+1;
	}
	dfs1(1, -1);
	dfs2(1, -1, 0, n);
	for(int i = 1; i <= n; ++ i)
		printf("%d ", ans[i]);
	puts("");
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
bool vis[1501];
int n, x233, y233, nume, h[1501], size[1501], point[1501];
struct edge { int v, nxt; } e[3001];
struct point {
  int x, y, id;
  bool operator < (const point &a) const {
    if (x >= x233 && a.x <= x233) return true;
    if (x <= x233 && a.x >= x233) return false;
    return 1ll * (a.x - x) * (y - y233) < 1ll * (a.y - y) * (x - x233);
  }
} p[1501];
void add_edge(int u, int v) {
  e[++nume].v = v, e[nume].nxt = h[u], h[u] = nume;
  e[++nume].v = u, e[nume].nxt = h[v], h[v] = nume;
}
int dfs(int u) {
  int ret = 0; vis[u] = true, size[u] = 1;
  for(int i = h[u]; i; i = e[i].nxt)
    if (!vis[e[i].v]) ret += dfs(e[i].v);
  size[u] += ret;
  return size[u];
}
void init(int u, int l, int r) {
  int t = l; vis[u] = true;
  for(int i = l + 1; i <= r; ++i)
    if ((p[i].y < p[t].y) || (p[t].y == p[i].y && p[i].x < p[t].x)) t = i;
  if (t != l) swap(p[l], p[t]);
  point[p[l].id] = u, x233 = p[l].x, y233 = p[l].y;
  sort(p + l + 1, p + r + 1);
  int pnt = l + 1;
  for (int i = h[u]; i; i = e[i].nxt)
    if (!vis[e[i].v]) {
      init(e[i].v, pnt, pnt + size[e[i].v] - 1);
      pnt += size[e[i].v];
    }
}
int main() {
  scanf("%d", &n);
  for(int i = 0; i < n - 1; ++i) {
    scanf("%d%d", &x233, &y233);
    add_edge(x233, y233);
  }
  for(int i = 1; i <= n; ++i) {
    scanf("%d%d", &x233, &y233);
    p[i].x = x233, p[i].y = y233, p[i].id = i;
  }
  dfs(1), memset(vis, false, sizeof vis), init(1, 1, n);
  for(int i = 1; i <= n; ++i) printf("%d ", point[i]);
  printf("\n");
  return 0;
}


/*
By Tianyi Chen. All rights reserved.
Date: 2016-07-24
*/
#include<bits/stdc++.h>
using namespace std;
vector<int>te[1501];bool visited[1501];
int n,_,__,subsize[1501],ans[1501];
struct point { int64_t x,y;int id;void read() { scanf("%lld%lld",&x,&y); } }p[1501];
int dfs(int i) {
 int rt=1;visited[i]=1;
 for (auto&&x:te[i])if (!visited[x])rt+=dfs(x);
 return subsize[i]=rt;
}
void build(int i,int b) {
 int est=b+subsize[i];
 visited[i]=1;
 swap(*min_element(p+b,p+b+subsize[i],[](const point&i,const point&j) {return i.y!=j.y?i.y<j.y:i.x<j.x;}),p[b]);
 sort(p+b+1,p+b+subsize[i],[&](const point&i,const point&j) {
  return (i.x-p[b].x)*(j.y-p[b].y)-(j.x-p[b].x)*(i.y-p[b].y)<0;
 });
 ans[p[b].id]=i;
 ++b;
 for (auto&&x:te[i])if (!visited[x]) {
  build(x,b);
  b+=subsize[x];
 }
 if (b!=est)throw;
}
int main() {
 scanf("%d",&n);for(int i=1;i<n;++i)scanf("%d%d",&_,&__),te[_].push_back(__),te[__].push_back(_);
 dfs(1);memset(visited,0,sizeof visited);
 for(int i=0;i<n;++i)p[i].id=i,p[i].read();
 build(1,0);
 for(int i=0;i<n;++i)printf("%d ",ans[i]);
}


//sobskdrbhvk
#include <bits/stdc++.h>

using namespace std;

typedef long long int LL;
typedef long double LD;
typedef pair<int, int> pii;
typedef pair<LL, LL> pll;
typedef complex<LL> Point;

#define PB push_back
#define MP make_pair
#define L first
#define R second
#define sz(x) ((int)(x).size())
#define smax(x, y) ((x) = max((x), (y)))
#define smin(x, y) ((x) = min((x), (y)))
#define all(x) x.begin(),x.end()

const int maxn = 1500 + 85 - 69;
vector<int> adj[maxn];
Point P[maxn];
int vec[maxn][maxn],
	vecsz[maxn],
	down[maxn],
	ans[maxn],
	n, cmpvert;

inline LL cross(Point x, Point y){
	return x.real() * y.imag() - x.imag() * y.real();
}

bool cmp(int i, int j){
	return cross(P[i] - P[cmpvert], P[j] - P[cmpvert]) > 0;
}

int rightmost(int id){
	int ret = vec[id][0];
	for(int i = 0; i < vecsz[id]; i++){
		int val = vec[id][i];
		if(P[val].real() > P[ret].real())
			ret = val;
	}
	return ret;
}

int dfs_preprocess(int v, int p = -1){
	down[v] = 1;
	for(auto u : adj[v])
		if(u != p)
			down[v] += dfs_preprocess(u, v);
	return down[v];
}

void dfs(int v, int vecid, int p = -1){
	int fv = rightmost(vecid);
	ans[fv] = v;
	int idtmp = find(vec[vecid], vec[vecid] + vecsz[vecid], fv) - vec[vecid];
	swap(vec[vecid][idtmp], vec[vecid][vecsz[vecid] - 1]);
	vecsz[vecid]--;
	cmpvert = fv;
	sort(vec[vecid], vec[vecid] + vecsz[vecid], cmp);
	int ptr = 0;
	for(int i = 0; i < sz(adj[v]); i++) if(adj[v][i] != p){
		int u = adj[v][i];
		for(int j = ptr; j < ptr + down[u]; j++)
			vec[vecid + 1][j - ptr] = vec[vecid][j];
		vecsz[vecid + 1] = down[u];
		ptr += down[u];
		dfs(u, vecid + 1, v);
	}
	return;
}

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	for(int i = 1; i < n; i++){
		int fi, se;
		cin >> fi >> se;
		fi--, se--;
		adj[fi].PB(se);
		adj[se].PB(fi);
	}
	for(int i = 0; i < n; i++){
		LL xx, yy;
		cin >> xx >> yy;
		P[i] = Point(xx, yy);
		vec[0][vecsz[0]++] = i;
	}
	dfs_preprocess(0);
	dfs(0, 0);
	for(int i = 0; i < n; i++)
		cout << ans[i] + 1 << ' ';
	cout << '\n';
	return 0;
}


#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

typedef long long ll;
const int MAXN = 1510, MAXM = 1510;
int n, m, sum;
int ans[MAXN], son[MAXN], last[MAXN];
struct Edge {
	int link, to;
} edge[MAXM << 1];
struct Node {
	int real;
	ll x, y;
} a[MAXN], tmp;

inline void add(int u, int v) {
	edge[++sum] = (Edge) { v, last[u] }, last[u] = sum;
	return;
}

inline int cmp1(Node a, Node b) {
	return a.x < b.x || a.x == b.x && a.y < b.y;
}

inline int cmp2(Node P1, Node P2) {
	return (tmp.x - P1.x) * (tmp.y - P2.y) < (tmp.x - P2.x) * (tmp.y - P1.y);
}

void dfs1(int x, int fa) {
	son[x] = 1;
	for (int i = last[x]; i; i = edge[i].to) {
		int y = edge[i].link;
		if (y == fa) continue;
		dfs1(y, x);
		son[x] += son[y];
	}
	return;
}

void dfs2(int x, int fa, int l, int r) {
	sort(a + l, a + r + 1, cmp1);
	// for (register int i = l; i <= r; ++i) printf("%d ",a[i].real); puts("");puts("");
	ans[a[l].real] = x, tmp = a[l];
	sort(a + l + 1, a + r + 1, cmp2);
	int L = l + 1;
	for (int i = last[x]; i; i = edge[i].to) {
		int y = edge[i].link;
		if (y == fa) continue;
		dfs2(y, x, L, L + son[y] - 1), L += son[y];
	}
	return;
}

int main() {
	scanf("%d", &n);
	for (register int i = 1; i < n; ++i) {
		int u, v; scanf("%d%d", &u, &v);
		add(u, v), add(v, u);
	}
	for (register int i = 1; i <= n; ++i) { scanf("%lld%lld", &a[i].x, &a[i].y); a[i].real = i; }
	dfs1(1, 0);
	dfs2(1, 0, 1, n);
	for (register int i = 1; i < n; ++i) printf("%d ", ans[i]);
	printf("%d\n", ans[n]);
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <set>
#include <math.h>

using namespace std;

typedef pair<int,int> pii;

vector<vector<int> > a;
bool vis[2000];
vector<int> res;
pii pnt;
vector<pair<pii,int>> point;

bool comp(pair<pii,int> a,pair<pii,int> b)
{
	double x=pnt.first;
	double y=pnt.second;
	double alp1=(a.first.second-y)/sqrt((a.first.first-x)*(a.first.first-x)+(a.first.second-y)*(a.first.second-y));
	double alp2=(b.first.second-y)/sqrt((b.first.first-x)*(b.first.first-x)+(b.first.second-y)*(b.first.second-y));
	return (alp1<alp2);
}

int ver_amt(int v)
{
	int kol=1;
	vis[v]=true;
	for (int i=0;i<a[v].size();i++)
		if (!vis[a[v][i]])
			kol+=ver_amt(a[v][i]);
	vis[v]=false;
	return kol;
}

void F(int v,vector<pair<pii,int> >::iterator b,vector<pair<pii,int> >::iterator en)
{
	vis[v]=true;
	vector<pair<pii,int>>::iterator p=b;
	for (vector<pair<pii,int> >::iterator it=b+1;it!=en;it++)
	{
		if (it->first.first<p->first.first)
			p=it;
		else
			if (it->first.first==p->first.first && it->first.second<p->first.second)
				p=it;
	}
	res[p->second]=v+1;
	pnt=p->first;
	swap((*p),(*b));
	b++;
	sort(b,en,comp);
	int cnt=0,cur;
	for (int i=0;i<a[v].size();i++)
		if (!vis[a[v][i]])
		{
			cur=ver_amt(a[v][i]);
			F(a[v][i],b+cnt,b+cnt+cur);
			cnt+=cur;
		}
}

int main()
{
	//freopen("inp.txt","r",stdin);
	int n;
	cin >> n;
	a.resize(n);
	int u,v;
	for (int i=0;i<n-1;i++)
	{
		scanf("%d%d",&u,&v);
		u--,v--;
		a[u].push_back(v);
		a[v].push_back(u);
	}
	point.resize(n);
	int x,y;
	for (int i=0;i<n;i++)
	{
		scanf("%d%d",&x,&y);
		point[i].first=make_pair(x,y);
		point[i].second=i;
	}
	res.resize(n);
	F(0,point.begin(),point.end());
	for (int i=0;i<n;i++)
		printf("%d ",res[i]);
	printf("\n");
	return 0;
}


#include <stdio.h>
#include <bits/stdc++.h>

#define uint unsigned int
#define ll long long
#define ull unsigned long long
#define ld long double
#define rep(i, l, r) for (int i = l; i < r; i++)
#define repb(i, r, l) for (int i = r; i > l; i--)
#define sz(a) (int)a.size()
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)

using namespace std;

const int N = 1500;
const int inf = (int)1e9 + 1;
const ll big = (ll)1e18 + 1;
const int P = 239;
const int MOD = (int)1e9 + 7;
const int MOD1 = (int)1e9 + 9;
const double eps = 1e-9;
const double pi = atan2(0, -1);
const int ABC = 26;

struct Point
{
    ll x, y;
    int id;
    Point() {}
    Point(ll x, ll y) : x(x), y(y) {}
};

Point operator - (Point p1, Point p2) { return Point(p1.x - p2.x, p1.y - p2.y); }

ll operator * (Point p1, Point p2) { return p1.x * p2.x + p1.y * p2.y; }

ll operator % (Point p1, Point p2) { return p1.x * p2.y - p2.x * p1.y; }

Point a[N];
vector<int> g[N];
int sz[N];
int ans[N];

void dfs(int u, int par)
{
    sz[u] = 1;
    for (int v : g[u])
        if (v != par)
        {
            dfs(v, u);
            sz[u] += sz[v];
        }
}

void solve(int u, int par, int l, int r)
{
    ans[a[l].id] = u;
    int pos = l + 1;
    for (int v : g[u])
        if (v != par)
        {
            sort(a + pos + 1, a + pos + sz[v], [a, pos](Point p1, Point p2) { return (p1 - a[pos]) % (p2 - a[pos]) > 0; });
            solve(v, u, pos, pos + sz[v]);
            pos += sz[v];
        }
}

int main()
{
    //freopen("a.in", "r", stdin);
    //freopen("a.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.precision(20);
    //ll TL = 0.95 * CLOCKS_PER_SEC;
    //clock_t time = clock();
    int n;
    cin >> n;
    rep(i, 0, n - 1)
    {
        int u, v;
        cin >> u >> v;
        u--; v--;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(0, -1);
    rep(i, 0, n)
    {
        cin >> a[i].x >> a[i].y;
        a[i].id = i;
    }
    int f = 0;
    rep(i, 0, n)
        if (a[i].y < a[f].y || a[i].y == a[f].y && a[i].x < a[f].x)
            f = i;
    swap(a[0], a[f]);
    sort(a + 1, a + n, [a](Point p1, Point p2) { return (p1 - a[0]) % (p2 - a[0]) > 0; });
    solve(0, -1, 0, n);
    rep(i, 0, n)
        cout << ans[i] + 1 << " ";
    cout << "\n";
    return 0;
}


/*
http://codeforces.com/problemset/problem/196/C
Codeforces Round #124 (Div. 1)
C. Paint Tree
2012.6.12
����Ŀ���⡻��һ������ƽ����n�������꣬����ΰ����еĵ㻭��ƽ���ϡ�
���ⷨ����
�������Ե㰴������������ν�����
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1501;
typedef long long ll;
struct arr{
  int x,y,z;
}d[maxn];
int a[maxn*2][2],b[maxn],f[maxn],v[maxn];
int n,s;

void add(int i,int j){
  a[++s][0]=b[i];
  b[i]=s;
  a[s][1]=j;
}

void dfs(int k){
  int i,j;
  f[k]=1;
  for (i=b[k];i;i=a[i][0]){
    j=a[i][1];
    if (!f[j]){
      dfs(j);
      f[k]+=f[j];
    }
  }
}

bool cmp(arr i,arr j){
  return ((ll)i.x*j.y-(ll)i.y*j.x)>0;
}

void dfs(int k,int l,int r){
  int i,j=r,s;
  if (l>r) return ;
  for (i=l;i<r;i++)
    if (d[i].y<d[j].y) j=i;
  v[d[j].z]=k;
  if (l==r) return ;
  swap(d[j],d[l]);
  for (i=l+1;i<=r;i++) d[i].x-=d[l].x,d[i].y-=d[l].y;
  l++;
  sort(d+l,d+r+1,cmp);
  for (i=b[k];i;i=a[i][0]){
    j=a[i][1];
    if (f[j]<f[k]){
      dfs(j,l,l+f[j]-1);
      l+=f[j];
    }
  }
}

int main(){
  int i,j,k;
  scanf("%d",&n);
  for (k=1;k<n;k++){
    scanf("%d%d",&i,&j);
    add(i,j);
    add(j,i);
  }
  dfs(1);
  for (i=1;i<=n;i++){
    scanf("%d%d",&d[i].x,&d[i].y);
    d[i].z=i;
  }
  dfs(1,1,n);
  for (i=1;i<=n;i++) printf("%d ",v[i]);
  printf("\n");
  return 0;
}


//Fruit of Light
//FoL CC
//Apple Strawberry

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>

using namespace std;

#define For(i, n) for(int i = 0; i<(n); ++i)
#define ForEach(it, i) for(typeof i.begin() it = i.begin(); it!=i.end(); ++it)
#define eps 1e-7

typedef long long ll;
typedef pair<int, int> pii;
typedef long double real;

int N;
vector<int> E[1547];
vector<int> B[1547];
int velkosti[1547];
int otec[1547];
int pridelenie[1547];
int ach[1547];
int bod, vod;
pii P[1547];
real uhol[1547];

real predrat[1547][1547];

bool my_func(int a, int b){
    if (fabs(predrat[a][bod])<eps){
        int xa = P[a].first - P[bod].first;
        int ya = P[a].second - P[bod].second;
        real uhola = fmod(fabs(atan2(real(ya), real(xa))-uhol[vod]),real(2*M_PI));
        predrat[a][bod] = min(uhola, 2*M_PI-uhola);
    }
    if (fabs(predrat[b][bod])<eps){
        int xb = P[b].first - P[bod].first;
        int yb = P[b].second - P[bod].second;
        real uholb = fmod(fabs(atan2(real(yb), real(xb))-uhol[vod]),real(2*M_PI));
        predrat[b][bod] = min(uholb, 2*M_PI-uholb);
    }
    return predrat[a][bod]<predrat[b][bod];
}

int vel(int v){
    velkosti[v] = 1;
    For(i,E[v].size()){
        if (E[v][i]!=otec[v]){
            otec[E[v][i]] = v;
            velkosti[v]+=vel(E[v][i]);
        }
    }
    //printf("vel[%d] = %d\n", v, velkosti[v]);
    return velkosti[v];
}

void zadel(int v, int p){
    //printf("%d %d %d %lf\n", v, p, B[v].size(), uhol[v]);
    pridelenie[v] = p;
    ach[p] = v;
    For(i, E[v].size()){
        if (E[v][i] == otec[v]) continue;
        int pocet = velkosti[E[v][i]]-1;
        bod = p; vod = v;
        sort(B[v].begin(),B[v].end(),my_func);
        //printf("sort: ");
        //ForEach(it, B[v]) printf("%d ",*it);
        //printf("\n");
        For(j,pocet) {
            B[E[v][i]].push_back(B[v][B[v].size()-1]);
            B[v].pop_back();
        }
        int z = B[v][B[v].size()-1];
        B[v].pop_back();
        //printf("zzz %d %d %d\n",E[v][i], B[v].size(), z);
        uhol[E[v][i]] = atan2(P[z].second-P[p].second, P[z].first-P[p].first);
        zadel(E[v][i],z);
    }
}

int main(){
    int a,b;
    scanf("%d",&N);
    For(i,N-1) {
        scanf("%d%d",&a,&b); a--; b--;
        E[a].push_back(b);
        E[b].push_back(a);
    }
    int best = 0;
    For(i,N) {
        scanf("%d%d",&a,&b);
        P[i] = pii(a,b);
        if (P[best].first>P[i].first) best = i;
    }
    For(i,N) if (i!=best) B[0].push_back(i);
    For(i,N) For(j,N) predrat[i][j]=0;
    uhol[0] = M_PI/2;
    otec[0] = 0;
    vel(0);
    zadel(0,best);
    For(i,N) printf("%d%c",ach[i]+1,(i==N-1)?'\n':' ');
}


#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <map>
#include <string.h>

const int N=2010;
const int inf=0x3f3f3f3f;

using namespace std;

struct node
{
	int to,next;
}edge[N*10];

int box[N],ecnt;

void _make_edge(int from,int to)
{
	edge[ecnt].to=to;
	edge[ecnt].next=box[from];
	box[from]=ecnt++;
	return ;
}

void make_edge(int from,int to)
{
	_make_edge(from,to);
	_make_edge(to,from);
	return ;
}

int dis[N];

void dfs(int u,int p)
{
	//cout<<u<<" "<<p<<endl;
	dis[u]=1;
	for(int i=box[u];i+1;i=edge[i].next)
	{
		int v=edge[i].to;
		if(p==v) continue;
		dfs(v,u);
		dis[u]+=dis[v];
	}
	return ;
}

struct point
{
	int id;
	double x,y;
	point(){}
	point(double _x,double _y):x(_x),y(_y){}
	point operator - (const point &c) const
	{
		return point(x-c.x,y-c.y);
	}
	bool operator * (const point &c) const
	{
		return x*c.y>=y*c.x;
	}
}a[N],p0;

bool cmp(const point &a,const point &b)
{
	return (a-p0)*(b-p0);
}

bool cmpy(const point &a,const point &b)
{
	if(a.y!=b.y) return a.y<b.y;
	return a.x<b.x;
}

int ans[N];

void DFS(int u,int p,int n,point a[])
{
	sort(a,a+n,cmpy);
	ans[a[0].id]=u;p0=a[0];
	sort(a+1,a+n,cmp);
	int cnt=1;
	for(int i=box[u];i+1;i=edge[i].next)
	{
		int v=edge[i].to;
		if(v==p) continue;
		DFS(v,u,dis[v],&a[cnt]);
		cnt+=dis[v];
	}
	return ;
}

int main()
{
	int n;
	cin>>n;
	memset(box,-1,sizeof(box));ecnt=0;
	for(int i=0;i<n-1;i++)
	{
		int a,b;
		cin>>a>>b;
		make_edge(a,b);
	}
	for(int i=0;i<n;i++)
		cin>>a[i].x>>a[i].y,a[i].id=i+1;
	dfs(1,1);
	DFS(1,1,n,a);
	for(int i=1;i<=n;i++)
		printf("%d ",ans[i]);
	puts("");
	return 0;
}


#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2000;
struct node
{
    int to,nxt;
}edge[2*N];
struct point
{
    int x,y,id;
}p[N],poi;
int n,head[2*N],tot=0,ans[N],size[N];
void add(int u,int v)
{
    edge[++tot].to=v;
    edge[tot].nxt=head[u];
    head[u]=tot;
}
bool cmp(point a,point b)
{
    int ax=a.x-poi.x;
    int ay=a.y-poi.y;
    int bx=b.x-poi.x;
    int by=b.y-poi.y;
    if (ax>=0 && bx<=0) return true;
    if (ax<=0 && bx>=0) return false;
    return ax*by>ay*bx;
}
void dfs_size(int u,int fa)
{
    size[u]=1;
    for (int i=head[u];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if (v==fa) continue;
        dfs_size(v,u);
        size[u]+=size[v];
    }
}
void dfs(int l,int r,int u,int fa)
{
    int x=l;
    for (int i=l+1;i<=r;i++)
    {
        if (p[i].x<p[x].x || (p[i].x==p[x].x && p[i].y<p[x].y)) x=i;
    }
    swap(p[l],p[x]);
    ans[p[l].id]=u;
    poi=p[l];
    sort(p+l+1,p+r+1,cmp);
    int now=l+1;
    for (int i=head[u];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if (v==fa) continue;
        dfs(now,now+size[v]-1,v,u);
        now+=size[v];
    }
}
signed main()
{
    memset(head,0,sizeof(head));
    scanf("%lld",&n);
    for (int i=1,u,v;i<=n-1;i++)
    {
        scanf("%lld%lld",&u,&v);
        add(u,v);
        add(v,u);
    }
    for (int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&p[i].x,&p[i].y);
        p[i].id=i;
    }
    dfs_size(1,0);
    dfs(1,n,1,0);
    for (int i=1;i<=n;i++)
    {
        printf("%lld ",ans[i]);
    }
    return 0;
}


#include <string>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <sstream>
#include <cstddef>
#include <algorithm>
#include <utility>
#include <iterator>
#include <numeric>
#include <list>
#include <complex>
#include <cstdio>
#include <climits>
#include <iostream>
#include <fstream>

/*** TEMPLATE CODE STARTS HERE ***/

using namespace std;

typedef vector<int> vi;
typedef vector<string> vs;
typedef long long ll;
typedef complex<ll> pnt;
typedef pair<int, int> pii;

#define RA(x) (x).begin(), (x).end()
#define FE(i, x) for (typeof((x).begin()) i = (x).begin(); i != (x).end(); i++)
#define SZ(x) ((int) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

static void redirect(int argc, const char **argv)
{
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

static ll cross(const pnt &a, const pnt &b) { return imag(conj(a) * b); }
static ll cross(const pnt &a, const pnt &b, const pnt &c)
{
    return cross(b - a, c - a);
}

struct node
{
    int parent;
    vi edges;
    int size;
    int pntid;

    node() : parent(-1), size(0), pntid(-1) {}
};

static void prepare(vector<node> &nodes, int cur, int parent)
{
    node &n = nodes[cur];
    n.parent = parent;
    n.size = 1;
    for (int i = 0; i < SZ(n.edges); i++)
    {
        int y = n.edges[i];
        if (y != parent)
        {
            prepare(nodes, y, cur);
            n.size += nodes[y].size;
        }
    }
}

struct compareYX
{
    bool operator()(const pnt &a, const pnt &b) const
    {
        if (a.imag() != b.imag())
            return a.imag() < b.imag();
        else
            return a.real() < b.real();
    }

    bool operator()(const pair<pnt, int> &a, const pair<pnt, int> &b) const
    {
        return (*this)(a.first, b.first);
    }
};

struct compareAngle
{
    pnt base;

    compareAngle(const pnt &base) : base(base) {}

    bool operator()(const pnt &a, const pnt &b) const
    {
        return cross(base, a, b) > 0;
    }

    bool operator()(const pair<pnt, int> &a, const pair<pnt, int> &b) const
    {
        return (*this)(a.first, b.first);
    }
};

typedef vector<pair<pnt, int> > pntvec;

static void place(vector<node> &nodes, int cur, pntvec::iterator first, pntvec::iterator last)
{
    node &n = nodes[cur];
    assert(last - first == n.size);
    pntvec::iterator lo = min_element(first, last, compareYX());
    swap(*first, *lo);

    n.pntid = first->second;

    sort(first + 1, last, compareAngle(first->first));
    first++;
    for (int i = 0; i < SZ(n.edges); i++)
    {
        int y = n.edges[i];
        if (y != n.parent)
        {
            place(nodes, y, first, first + nodes[y].size);
            first += nodes[y].size;
        }
    }
}

int main(int argc, const char **argv)
{
    redirect(argc, argv);

    int N;
    cin >> N;
    vector<node> nodes(N);
    for (int i = 1; i < N; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        nodes[u].edges.push_back(v);
        nodes[v].edges.push_back(u);
    }
    prepare(nodes, 0, -1);

    vector<pair<pnt, int> > pnts;
    for (int i = 0; i < N; i++)
    {
        int x, y;
        cin >> x >> y;
        pnts.push_back(make_pair(pnt(x, y), i));
    }

    place(nodes, 0, pnts.begin(), pnts.end());
    vector<int> ans(N, -1);
    for (int i = 0; i < N; i++)
        ans[nodes[i].pntid] = i + 1;

    cout << ans[0];
    for (int i = 1; i < N; i++)
        cout << ' ' << ans[i];
    cout << '\n';

    return 0;
}


#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;

struct pt {
    int x, y, id;
};

vector < pt > p;
vector <vector <int> > g;
vector <int> size, ans;
int n;

int dfs(int v, int parent = -1) {
    for (int i = 0; i < g[v].size(); i++) {
        int to = g[v][i];
        if (to == parent) continue;
        size[v] += dfs(to, v);
    }
    return size[v];
}

int gx, gy;

bool cmp(pt a, pt b) {
    return 1LL*(a.x - gx)*(b.y - gy) - 1LL*(b.x - gx)*(a.y - gy) > 0;
}

bool cmp2(pt a, pt b) {
    return a.y > b.y || a.y == b.y && a.x < b.x;
}

void rec(int v, vector <pt> p, int parent = -1) {
    gx = p.front().x, gy = p.front().y;
    ans[p.front().id] = v;
    p.erase(p.begin());
    sort(p.begin(), p.end(), cmp);

    vector <pt> buf;
    int cur = 0;
    for (int i = 0; i < g[v].size(); i++) {
        int to = g[v][i];

        if (to != parent) {
            buf.clear();
            for (int x = cur; cur < x + size[to]; cur++) {
                buf.push_back(p[cur]);
            }

            rec(to, buf, v);
        }
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    cin >> n;
    g.resize(n);
    p.resize(n);
    ans.resize(n);
    size.assign(n, 1);

    for (int i = 0; i < n-1; i++) {
        int a, b;
        cin >> a >> b;
        g[--a].push_back(--b);
        g[b].push_back(a);
    }

    for (int i = 0; i < n; i++) {
        cin >> p[i].x >> p[i].y;
        p[i].id = i;
    }

    dfs(0);
    sort(p.begin(), p.end(), cmp2);
    rec(0, p);

    for (int i = 0; i < n; i++)
        cout << (ans[i]+1)  << " ";

    return 0;
}


#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

#define FOR(i,s,t) for(int i=(s),_t=(t);i<=_t;++i)
#define DOR(i,s,t) for(int i=(s),_t=(t);i>=_t;--i)
#define M 1505

typedef long long ll;

vector<int> E[M];

ll pos_x,pos_y;
struct node{
	int x,y,id;
	bool operator <(const node &s) const{
		return y<s.y;
	}
}A[M];

bool cmp(node a,node b) {
	return (a.x-pos_x)*(b.y-pos_y)>(a.y-pos_y)*(b.x-pos_x);
}

int Ans[M];

int Fa[M],sz[M];
void dfs(int x,int fr) {
	Fa[x]=fr;sz[x]=1;
	FOR(i,0,E[x].size()-1) {
		int y=E[x][i];
		if(y==fr) continue;
		dfs(y,x);
		sz[x]+=sz[y];
	}
}
void solve(int L,int R,int x) {
	int s=L;
	FOR(i,L+1,R) if(A[s].x>A[i].x) s=i;
	node tmp=A[L];
	A[L]=A[s];
	A[s]=tmp;
	Ans[A[L].id]=x;
	pos_x=A[L].x;
	pos_y=A[L].y;
	L++;
	if(L>R) return ;
	sort(A+L,A+R+1,cmp);
	FOR(i,0,E[x].size()-1) {
		int y=E[x][i];
		if(y==Fa[x]) continue;
		solve(L,L+sz[y]-1,y);
		L+=sz[y];
	}
}
int main() {
	int n;
	scanf("%d",&n);
	FOR(i,2,n) {
		int x,y;
		scanf("%d%d",&x,&y);
		E[x].push_back(y);
		E[y].push_back(x);
	}
	FOR(i,1,n) {
		scanf("%d%d",&A[i].x,&A[i].y);
		A[i].id=i;
	}
	dfs(1,0);
	solve(1,n,1);
	FOR(i,1,n) printf("%d ",Ans[i]);
	putchar('\n');
	return 0;
}


#include<bits/stdc++.h>
#define pb push_back
#define pp pop_back()
#define mp make_pair
#define fr first
#define sc second
#define sz size()
#define smin(x,y) ((x)=min((x),(y)))
#define smax(x,y) ((x)=max((x),(y)))
#define all(x) x.begin(),x.end()
#define CS ios_base::sync_with_stdio(false);
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;
typedef vector<int> vi;
typedef pair<ll,ll> pll;
const int M=1505;
pll a[M];
int mark[M],dp[M],n;
vi adj[M];
void dfs(int v){
	mark[v]=1;
	for(int u : adj[v]) if(!mark[u])
		dfs(u),dp[v]+=dp[u];
	dp[v]++;
}
bool cmp_up(int u,int v){
	return a[u].sc<a[v].sc;
}
int comper;
bool cmp_shib(int u,int v){
	ll s1 = a[u].fr-a[comper].fr;
	ll s2 = a[u].sc-a[comper].sc;
	ll t1 = a[v].fr-a[comper].fr;
	ll t2 = a[v].sc-a[comper].sc;
	return s2*t1<s1*t2;
}
int mat[M];
void solve(vector<int> vec,int v){
	auto it = max_element(all(vec),cmp_up);
	int root = *it; vec.erase(it);
	comper = root;
	sort(all(vec),cmp_shib);
	vi go;
	for(int u : adj[v]) if(dp[u]<dp[v]){
		go.clear();
		int siz = dp[u];
		while(siz--) go.pb(vec.back()),vec.pp;
		solve(go,u);
	}
	mat[root]=v;
}
int32_t main()
{
	cin>>n;
	for(int i=1;i<n;i++){
		int u,v; cin>>u>>v;
		adj[u].pb(v),adj[v].pb(u);
	}
	vi vec;
	for(int i=1;i<=n;i++) cin>>a[i].fr>>a[i].sc,vec.pb(i);
	dfs(1),solve(vec,1);
	for(int i=1;i<=n;i++) cout<<mat[i]<<' ';
	return cout<<endl,0;
}


#include <cassert>
#include <bitset>
#include <algorithm>
#include <functional>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
using namespace std;

#define sz(a) static_cast<int>(a.size())
#define all(a) a.begin(), a.end()
#define rep(i, a, b) for(int i=int(a); i<=int(b); ++i)
#define irep(i, a, b) for(int i=int(a); i>=int(b); --i)
#define repn(i, n) rep(i, 0, (n)-1)
#define irepn(i, n) irep(i, (n)-1, 0)
#define fillchar(a, x) memset(a, x, sizeof(a))
#define fi first
#define se second
#define pb push_back
#define mp make_pair
typedef long long LL;
typedef pair<LL,LL> PLL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
typedef vector<LL> VL;
typedef vector<int> VI;
typedef vector<PII> VPI;
typedef vector<string> VS;
template<class T> bool setmax(T &_a, T _b) { if(_b>_a) { _a=_b; return true; } return false; }
template<class T> bool setmin(T &_a, T _b) { if(_b<_a) { _a=_b; return true; } return false; }
template<class T> T gcd(T _a, T _b) { return _b==0?_a:gcd(_b,_a%_b); }

const int N=2010;

struct Formula {
    bitset<N> g[N]; int r[N];
    int n, m;
    int op(int x) const { return x<=n ? x+n : x-n; }

    void read(int _n, int _m) {
        n=_n; m=_m;
        rep(i, 1, n*2) g[i].reset();
        rep(i, 1, m) {
            int a, b; scanf("%d%d", &a,&b);
            if(a<0) a=-a+n;
            if(b<0) b=-b+n;
            g[op(a)][b]=1;
            g[op(b)][a]=1;
        }
    }

    void go() {
        rep(k, 1, n*2) rep(i, 1, n*2) if(g[i][k]) {
            g[i]|=g[k];
        }

        if(ok()) {
            fillchar(r, 0xff);
            rep(x, 1, n*2) if(g[op(x)][x]) color(x);
        }
    }

    void color(int x) {
        if(r[x]>=0) { assert(r[x]==1); return; }
        r[x]=1, r[op(x)]=0;
        rep(y, 1, n*2) if(g[x][y]) color(y);
    }

    bool ok() {
        rep(x, 1, n) if(g[x][x+n] && g[x+n][x]) return false;
        return true;
    }

    void solve(int c1=-1, int c2=-1) {
        if(c1>0) color(c1);
        if(c2>0) color(c2);
        rep(i, 1, n*2) if(r[i]<0) color(i);
        rep(i, 1, n) printf("%d ", r[i]); printf("\n");
        exit(0);
    }
};

Formula f, g;

int main() {
    int n, m1, m2; scanf("%d%d%d", &n,&m1,&m2);
    f.read(n, m1); f.go();
    g.read(n, m2); g.go();
    bool of=f.ok(), og=g.ok();
    if(of && !og) f.solve();
    else if(!of && og) g.solve();
    else if(of && og) {
        rep(i, 1, n*2) {
            if(f.r[i]==0 && g.r[i]!=0) g.solve(i);
            if(g.r[i]==0 && f.r[i]!=0) f.solve(i);
        }
        rep(i, 1, n*2) rep(j, 1, n*2) if(i!=j && f.r[i]<0 && f.r[j]<0) {
            if(f.g[i][j]!=g.g[i][j]) {
                if(f.g[i][j]) g.solve(i, g.op(j));
                if(g.g[i][j]) f.solve(i, f.op(j));
            }
        }
    }
    printf("SIMILAR\n");

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define sqr(x) ((x)*(x))
#define mp make_pair
#define uint unsigned
#define PI pair<ll,ll>
#define fi first
#define se second
#define ld long double
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline ll read(){
	ll x = 0; char ch = gc(); bool positive = 1;
	for (; !isdigit(ch); ch = gc())	if (ch == '-')	positive = 0;
	for (; isdigit(ch); ch = gc())	x = x * 10 + ch - '0';
	return positive ? x : -x;
}
inline void write(ll a){
    if(a<0){
    	a=-a; putchar('-');
	}
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
inline void writeln(ll a){write(a); putchar('\n');}
inline void wri(ll a){write(a); putchar(' ');}
const int N=100005;
int x[N],y[N],lx,ly,Ans;
set<pair<int,int> > M;
ll q[N];
PI ans[N];
bool vis[N];
int main(){
	//freopen("akitomoya.in","r",stdin);freopen("akitomoya.out","w",stdout);
	int n=read();
	for(int i=1;i<=n;i++){
		x[i]=read(); y[i]=read();
	}
	int ho=0;
	if(n%2==0){
		n--; ho=1;
	}
	for(int i=1;i<=n;i++){
		ll tx=ho?x[i]+x[n+1]:x[i]*2,ty=ho?y[i]+y[n+1]:y[i]*2;
		if(M.count(mp(tx,ty)))continue; else M.insert(mp(tx,ty));
		ll sumx=0,sumy=0;
		for(int j=1;j<=n;j++)if(i!=j){sumx+=x[j]; sumy+=y[j];}
		//cout<<tx<<" "<<ty<<" "<<sumx<<" "<<sumy<<endl;
		if(sumx!=tx*((n-1)/2)||sumy!=ty*((n-1)/2)){//cout<<i<<" pt"<<endl;
			ll S=ty*(n-1)/2-sumy,T=sumx-tx*(n-1)/2; *q=0;
			for(int j=1;j<=n;j++)if(i!=j)q[++*q]=(x[j])*S+(y[j])*T;
			sort(&q[1],&q[*q+1]);
			int f=1;
			ll t=tx*S+ty*T;
			for(int j=1;j<=*q/2&&f;j++)if(q[j]+q[*q-j+1]!=t)f=0;
			//cout<<f<<" "<<i<<" "<<S<<" "<<T<<" "<<t<<endl;
			if(f)ans[Ans++]=mp(S,T);
		}else{//cout<<i<<endl;
			int fff=1; vis[i]=1;
			for(int j=1;j<=n;j++)if(i!=j&&!vis[j]){
				int f=1;
				for(int k=j+1;k<=n&&f;k++)if(i!=k&&x[k]+x[j]==tx&&y[k]+y[j]==ty&&!vis[k]){
					vis[k]=vis[j]=1; f=0;
				}
				if(f){//cout<<i<<" "<<j<<" "<<f<<endl;
					fff=0;
					for(int k=j;k<=n;k++)if(!vis[k]){
						ll S=y[j]+y[k]-ty,T=tx-x[j]-x[k]; *q=0;

						for(int l=j;l<=n;l++)if(!vis[l]){
							q[++*q]=S*x[l]+T*y[l];
						}
						sort(&q[1],&q[*q+1]);

						ll t=tx*S+ty*T;
						int f=1;
						for(int j=1;j<=*q/2&&f;j++)if(q[j]+q[*q-j+1]!=t)f=0; //cout<<f<<" "<<j<<" "<<k<<" "<<S<<" "<<T<<endl;
						if(f)ans[Ans++]=mp(S,T);
					}
					break;
				}
			}
			if(fff){
				puts("-1"); return 0;
			}
		}
	}
	int tot=0;
	for(int i=0;i<Ans;i++){
		int f=1;
		for(int j=0;j<i&&f;j++)if(ans[i].fi*ans[j].se==ans[i].se*ans[j].fi)f=0;
		tot+=f;
		//cout<<i<<" "<<ans[i].fi<<" "<<ans[i].se<<endl;
		//for(int j=1;j<=n;j++)cout<<ans[i].fi*x[j]+ans[i].se*y[j]<<endl;
	}
	cout<<tot<<endl;
}
/*
7
0 0
2 2
1 -1
-1 2
-2 -1
4 4
-4 -5
6 6
-6 -7
*/


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

typedef long long LL;
typedef double Type;

const double eps = 1e-8;
const double PI = 3.1415926535;

#define IS(X) cout << #X << " = " << (X) << endl

inline int sgn(Type x) {
    return (x > eps) - (x < -eps);
}

struct Point {
    Type x, y, id;
    Point() : x(0), y(0) {}

    Point(Type _x, Type _y) : x(_x), y(_y) {}

    void set(Type _x, Type _y) {
        this->x = _x; this->y = _y;
    }

    Point operator + (const Point &p) const {
        return Point(x + p.x,  y + p.y);
    }

    Point operator - (const Point &p) const {
        return Point(x - p.x, y - p.y);
    }

    Point operator * (const Type &q) const {
        return Point(x * q, y * q);
    }

    Point operator / (const Type &q) const {
        return Point(x / q, y / q);
    }

    bool operator == (const Point &p) const {
        return fabs(p.x - x) < eps && fabs(p.y - y) < eps;
    }

    bool operator != (const Point &p) const {
        return ((*this) == p) == false;
    }

    friend bool operator < (const Point &p1, const Point &p2) {
        return p1.y < p2.y || (p1.y == p2.y && p1.x < p2.x);
    }

    void read() {
        cin >> this->x >> this->y;
    }

    void print() const {
        cout << "Point" << x << "," << y << endl;
    }
};

inline Type Dot(const Point &p1, const Point &p2) {
    return p1.x * p2.x + p1.y * p2.y;
}

inline Type Cross(const Point &p1, const Point &p2) {
    return p1.x * p2.y - p2.x * p1.y;
}

inline Type Length2(const Point &p1) {
    return p1.x * p1.x + p1.y * p1.y;
}

inline Type Length(const Point &p) {
    return sqrt(Length2(p));
}

inline Type Angle(const Point &p) {
    return atan2(p.y, p.x);
}

int n;
Point p[2005];
Point cp[2005];
Point o(0,0);
bool use[2005];
int main() {
    cin >> n;
    for(int i = 1;i <= n;i++) {
        p[i].read();p[i].id = i;
        o = o + p[i];
    }
    o = o / n;
    for(int i = 1;i <= n;i++) use[i] = true;
    for(int i = 1;i <= n;i++) {
        if(!use[i]) continue;
        if(Length(p[i] - o) == 0) {
            use[i] = false; continue;
        }
        for(int j = i + 1;j <= n;j++) {
            if(!use[j]) continue;
            if(sgn( Length((p[i] + p[j]) / 2 - o) == 0 )) {
                use[i] = use[j] = false;
                break;
            }
        }
    }
    int pos = 0;
    for(int i = 1;i <= n;i++) {
        if(use[i]) swap(p[++pos], p[i]);
    }
    if(pos == 0) {
        cout << "-1" << endl;return 0;
    }
    int ans = 0;
    vector<Point> dir;dir.clear();
    for(int i = 1;i <= pos;i++) {
        Point mid = (p[1] + p[i]) / 2;
        Point k = (mid - o) / Length((mid - o));
        bool flag = true;
        for(int j = 0;j < dir.size();j++) {
            if(dir[j] == k || dir[j] + k == Point(0,0)) {
                flag = false;break;
            }
        }
        if(!flag) continue;
        dir.push_back(k);
        vector<Type> v;
        v.clear();
        for(int j = 1;j <= pos;j++) {
             v.push_back(Cross(p[j] - o, mid - o));
        }
        sort(v.begin(), v.end());
        flag = true;
        int b = 0, e = v.size() - 1;
        for(;b <= e;b++, e--) {
            if(sgn(v[b] + v[e]) != 0) {
                flag = false; break;
            }
        }
        if(flag) ans ++;
    }
    cout << ans << endl;
    return 0;
}