← 全部文章

ARC095F Permutation Tree 题解

本文目录(3 节)
  1. 题意
  2. 题解
  3. 代码

ARC095F Permutation Tree

题意

  • 对于一个 1∼n1\sim n 的排列 p1⋯np_{1\cdots n},可以通过如下方法生成一棵树:
    • 对于 ii,如果 pi≠1p_i \ne 1,则找到一个最大的 jj 满足 pj<pip_j < p_i,在 i,ji,j 之间连边。
  • 现在要求找到一个字典序最小的生成的树与给定的树同构的排列,或判断无解。
  • n≤105n \le 10^5。

题解

给定树必须要是一个毛毛虫,即去掉叶子之后要是一条链。

正反方向贪心一下,取字典序更小的方案即可。

代码

const int N = 1e5 + 7;
int n, d[N], c[N], l, r;
vi e[N];
bool v[N];

inline int find(int x) {
	for (int y : e[x])
		if (!v[y] && d[y] != 1) return y;
	return 0;
}

inline vi work(int l, int r) {
	vi ret(1, 1), p(1, d[l] - 2);
	for (int i = 1; i <= n; i++) v[i] = 0;
	while (l != r) v[l] = 1, l = find(l), p.pb(d[l] - 2);
	int t = 1;
	for (int x : p) {
		dbg(x);
		for (int i = 1; i <= x; i++) ret.pb(t + i + 1);
		ret.pb(t + 1), t += x + 1;
	}
	ret.pb(n);
	return ret;
}

int main() {
	rd(n);
	if (n == 2) return prints("1 2"), 0;
	for (int i = 1, x, y; i < n; i++)
		rd(x, y), e[x].pb(y), e[y].pb(x), ++d[x], ++d[y];
	for (int i = 1; i <= n; i++) c[i] = d[i];
	for (int i = 1; i <= n; i++)
		if (d[i] == 1) --c[e[i][0]], --c[i];
	if (*max_element(c + 1, c + n + 1) > 2) return print(-1), 0;
	if (!*max_element(c + 1, c + n + 1)) {
		print(1, ' ');
		for (int i = 3; i < n; i++) print(i, ' ');
		print(2, ' '), print(n);
		return 0;
	}
	for (int i = 1; i <= n; i++)
		if (c[i] == 1) r = i;
	for (int i = n; i; i--)
		if (c[i] == 1) l = i;
	vi ans = min(work(l, r), work(r, l));
	for (int x : ans) print(x, ' ');
	return 0;
}

标签:贪心

评论

    填写昵称即可留言。评论经站主审核后公开,请勿提交私人信息。

    正在连接评论服务…