[CF2040D] Non Prime Tree 题解

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

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

  1. \(mxd \geq 5\) 时,直接按层填充。
  2. \(mxd = 2\) 时,直接输出 1 2\n
  3. \(mxd = 3\) 时,按层数 \(2 \to 1 \to 3\) 填,再把根结点减一。
  4. \(mxd = 4\) 时,按层数 \(3 \to 1 \to 2 \to 4\) 填,再把根结点加一。

做完了。

#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 @ 2024-12-22 10:00  Water_M  阅读(31)  评论(0)    收藏  举报