见证者为见证而来,铭记者因铭记而生|

园龄:粉丝:关注:

[CF2040D] Non Prime Tree 题解

传送门
构造题做得较少,所以性质观察得较慢。
值域给的 2n 非常诡异,想到考虑 2 的倍数。
按深度记录下每层结点,发现隔一层依次按 2 的倍数填充,即可满足。
即:先填奇数层,再填偶数层。
但是连续的偶数是不能相邻的,发现当深度在 [2,4] 时,无论以何顺序按层填充,都会有问题。

处理方法:
我们尽量让出问题的结点在度最小的结点。这样就可以调整最少数量的结点。
方便起见,尽量让根结点的度最小。我们只需指定一个叶结点为新根即可,按新根计算深度等。
于是按树的深度 mxd 分类:

  1. mxd5 时,直接按层填充。
  2. mxd=2 时,直接输出 1 2\n
  3. mxd=3 时,按层数 213 填,再把根结点减一。
  4. mxd=4 时,按层数 3124 填,再把根结点加一。

做完了。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Linf 0x3f3f3f3f3f3f3f3f
#define pii pair<int, int> 
#define all(v) v.begin(), v.end()
using namespace std;

//#define filename "xxx" 
#define FileOperations() freopen(filename".in", "r", stdin), freopen(filename".out", "w", stdout)


namespace Traveller {
	const int N = 2e5+2;
	
	int n;
	vector<int> g[N];
	
	int dep[N], leaf, mxd;
	void DFS1(int u, int fa) {
		leaf = u;
		for(auto v : g[u]) {
			if(v == fa) continue;
			DFS1(v, u);
		}
	}
	
	vector<int> p[N];
	void DFS2(int u, int fa) {
		dep[u] = dep[fa] + 1;
		mxd = max(mxd, dep[u]);
		p[dep[u]].push_back(u);
		for(auto v : g[u]) {
			if(v == fa) continue;
			DFS2(v, u);
		}
	}
	
	int a[N];
	
	void main() {
		cin >> n;
		for(int i = 1; i <= n; ++i) g[i].clear(), p[i].clear();
		
		for(int i = 1, u, v; i < n; ++i) {
			scanf("%d%d", &u, &v);
			g[u].push_back(v), g[v].push_back(u);
		}
		
		mxd = 0;
		DFS1(1, 0), DFS2(leaf, 0);
		if(mxd == 2) printf("1 2\n");
		else if(mxd == 3) {
			int k = 2;
			a[p[2][0]] = k, k += 2;
			a[p[1][0]] = k-1, k += 2;
			for(auto u : p[3]) a[u] = k, k += 2;
			for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
			puts("");
		}
		else if(mxd == 4) {
			int k = 2;
			for(auto u : p[3]) a[u] = k, k += 2;
			a[p[1][0]] = k+1, k += 2;
			a[p[2][0]] = k, k += 2;
			for(auto u : p[4]) a[u] = k, k += 2;
			for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
			puts("");
		}
		else {
			int k = 2;
			for(int d = 1; d <= mxd; d += 2)
				for(auto u : p[d]) a[u] = k, k += 2;
			for(int d = 2; d <= mxd; d += 2)
				for(auto u : p[d]) a[u] = k, k += 2;
			for(int i = 1; i <= n; ++i) printf("%d ", a[i]);
			puts("");
		}
	}
}

signed main() {
	#ifdef filename
		FileOperations();
	#endif
	
	int _;
	cin >> _;
	while(_--) Traveller::main();
	return 0;
}


posted @   wfc284  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起