CodeForces - 197E Paint Tree(极角排序+贪心)

本文介绍了如何使用极角排序和贪心策略解决CodeForces 197E问题,即如何在不使线段相交的情况下将一棵树的节点映射到平面直角坐标系的点上。首先选择坐标最左下角的点作为树的根节点,然后对剩余点进行极角排序,按照逆时针方向依次分配节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://codeforces.com/problemset/problem/197/E
题意:给你一棵n个点的树和n个直角坐标系上的点,现在要把树上的n个点映射到直角坐标系的n个点中,要求是除了在顶点处不能有线段的相交。
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.

Examples
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.

[外链图片转存失败(img-N9ZDridJ-1568001269754)(https://vj.e949.cn/1393d68e352392e8df5e96273e5f31e2?v=1549972047)][外链图片转存失败(img-xOQ8Pl2F-1568001269755)(https://vj.e949.cn/0837595ef0b4cbb2b7dfbb94c8c69f70?v=1549972047)]

极角排序+贪心
我们先选一个在直角坐标系中的最左下角的点,把根结点放到这个点中,然后对剩下的点进行极角排序,按逆时针顺序处理。
如图所示:(该图来自网络)

来自网络

#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;//找到p[i] (l<=i<=r)中最左下角的点
    }
    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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值