[CodeForces - 197E] E - Paint Tree

E - Paint Tree

You are given a tree with n vertexes and n points on a plane, no three points lie on one straight line.

Your task is to paint the given tree on a plane, using the given points as vertexes.

That is, you should correspond each vertex of the tree to exactly one point and each point should correspond to a vertex. If two vertexes of the tree are connected by an edge, then the corresponding points should have a segment painted between them. The segments that correspond to non-adjacent edges, should not have common points. The segments that correspond to adjacent edges should have exactly one common point.

Input

The first line contains an integer n (1 ≤ n ≤ 1500) — the number of vertexes on a tree (as well as the number of chosen points on the plane).

Each of the next n - 1 lines contains two space-separated integers ui and vi (1 ≤ ui, vi ≤ nui ≠ vi) — the numbers of tree vertexes connected by the i-th edge.

Each of the next n lines contain two space-separated integers xi and yi ( - 109 ≤ xi, yi ≤ 109) — the coordinates of the i-th point on the plane. No three points lie on one straight line.

It is guaranteed that under given constraints problem has a solution.

Output

Print n distinct space-separated integers from 1 to n: the i-th number must equal the number of the vertex to place at the i-th point (the points are numbered in the order, in which they are listed in the input).

If there are several solutions, print any of them.

Example

Input
3
1 3
2 3
0 0
1 1
2 0
Output
1 3 2
Input
4
1 2
2 3
1 4
-1 -2
3 5
-3 3
2 0
Output
4 2 1 3

Note

The possible solutions for the sample are given below.

 

题目意思就是,给你一棵已经定型的无根树,然后在二维屏幕上给出几个坐标,要求将树的每一个节点对应到二维平面上的每一个点上,要求形成的是一棵正常的树.

这题完全没思路,只知道肯定是排序+DFS,然而,就是没有想的更深一点——极角排序+分治.

我们每次递归分治的的时候,标记的总是一段区间,这个区间是有一定顺序的,他按照基准点极角排序.为什么极角排序就一定对呢?

因为每一次,你找的相当于在凸多边形上这个点的下几个点,不会穿越其他线段,这段区间也会被覆盖满(极角排序的性质很适用).最后输出就好了,效率应该是n^nlogn的。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define LL long long
 5 using namespace std;
 6 const int maxn=1505,maxe=3005;
 7 int size[maxn],fa[maxn];
 8 int n,tot,nxt[maxe],son[maxe],lnk[maxn],ans[maxn];
 9 bool vis[maxn];
10 struct point{int x,y,id;}a[maxn],mainp;
11 point operator - (point p,point q){point ret; ret.x=p.x-q.x,ret.y=p.y-q.y; return ret;}
12 LL cross(point p,point q){return (LL)p.x*q.y-(LL)q.x*p.y;}
13 bool cmp1(point u,point v){return u.x!=v.x?u.x<v.x:u.y<v.y;}
14 bool cmp2(point u,point v){return cross(u-mainp,v-mainp)<0;}
15 int read(){
16     int x=0,f=1; char ch=getchar();
17     while (ch<'0'||ch>'9'){if (ch=='-') f=-f; ch=getchar();}
18     while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
19     return x*f;
20 }
21 void add(int x,int y){nxt[++tot]=lnk[x],son[tot]=y,lnk[x]=tot;}
22 void DFS(int x){
23     vis[x]=1,size[x]=1;
24     for (int j=lnk[x]; j; j=nxt[j]) if (!vis[son[j]]){
25         DFS(son[j]); size[x]+=size[son[j]];
26     }
27 }
28 void DFS(int x,int fa,int L,int R){
29     sort(a+L,a+1+R,cmp1);
30     ans[a[L].id]=x,mainp.x=a[L].x,mainp.y=a[L].y;
31     sort(a+1+L,a+1+R,cmp2);
32     int now=L;
33     for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=fa){
34         DFS(son[j],x,now+1,now+size[son[j]]),now+=size[son[j]];
35     }
36 }
37 int main(){
38     n=read(),tot=0;
39     for (int i=1; i<n; i++){int x=read(),y=read(); add(x,y),add(y,x);}
40     memset(vis,0,sizeof vis),memset(size,0,sizeof size),DFS(1);
41     for (int i=1; i<=n; i++) a[i].x=read(),a[i].y=read(),a[i].id=i;
42     DFS(1,1,1,n);
43     for (int i=1; i<=n; i++) printf("%d ",ans[i]);
44     return 0;
45 }
View Code

 

转载于:https://www.cnblogs.com/whc200305/p/7214453.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值