构造题做得较少,所以性质观察得较慢。
值域给的 \(2n\) 非常诡异,想到考虑 \(2\) 的倍数。
按深度记录下每层结点,发现隔一层依次按 \(2\) 的倍数填充,即可满足。
即:先填奇数层,再填偶数层。
但是连续的偶数是不能相邻的,发现当深度在 \([2, 4]\) 时,无论以何顺序按层填充,都会有问题。
处理方法:
我们尽量让出问题的结点在度最小的结点。这样就可以调整最少数量的结点。
方便起见,尽量让根结点的度最小。我们只需指定一个叶结点为新根即可,按新根计算深度等。
于是按树的深度 \(mxd\) 分类:
- \(mxd \geq 5\) 时,直接按层填充。
- \(mxd = 2\) 时,直接输出
1 2\n
。 - \(mxd = 3\) 时,按层数 \(2 \to 1 \to 3\) 填,再把根结点减一。
- \(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 filenameFileOperations();#endifint _;cin >> _;while(_--) Traveller::main();return 0;
}