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 ≤ n, ui ≠ 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
3
1 3
2 3
0 0
1 1
2 0
1 3 2
4
1 2
2 3
1 4
-1 -2
3 5
-3 3
2 0
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 }