1. 程式人生 > >Codeforces 196C Paint Tree(貪心+極角排序)

Codeforces 196C Paint Tree(貪心+極角排序)

cpp namespace paint 進行 滿足 sin its force 一個個

題目鏈接 Paint Tree

給你一棵n個點的樹和n個直角坐標系上的點,現在要把樹上的n個點映射到直角坐標系的n個點中,要求是除了在頂點處不能有線段的相交。

我們先選一個在直角坐標系中的最左下角的點,把根結點放到這個點中,然後對剩下的點進行極角排序,按逆時順序一個個塞進來,類似地遞歸處理。

這樣就滿足了題意。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 1510;

int X, Y;

struct node{
	int x, y;
	int id;
	friend bool operator < (const node &a, const node &b){
		return (LL)(a.y - Y) * (b.x - X) < (LL)(b.y - Y) * (a.x - X);
	}
} p[N];

vector <int> v[N];
int sz[N], ans[N];
int n;

void dfs(int x, int fa){
	sz[x] = 1;
	for (auto u : v[x]){
		if (u == fa) continue;
		dfs(u, x);
		sz[x] += sz[u];
	}
}

void calc(int x, int fa, int l, int r){
	int t = l;
	rep(i, l + 1, r){
		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]);
	ans[p[l].id] = x;
	X = p[l].x, Y = p[l].y;
	sort(p + l + 1, p + r + 1);
	int pos = l + 1;

	for (auto u : v[x]){
		if (u == fa) continue;
		calc(u, x, pos, pos + sz[u] - 1);
		pos += sz[u];
	}
}

int main(){

	scanf("%d", &n);
	rep(i, 1, n - 1){
		int x, y;
		scanf("%d%d", &x, &y);
		v[x].push_back(y);
		v[y].push_back(x);
	}

	rep(i, 1, n){
		int x, y;
		scanf("%d%d", &x, &y);
		p[i] = {x, y, i};
	}

	dfs(1, 0);
	calc(1, 0, 1, n);
	rep(i, 1, n) printf("%d\n", ans[i]);

	return 0;
}

Codeforces 196C Paint Tree(貪心+極角排序)