[CF2040D] Non Prime Tree 题解
传送门
构造题做得较少,所以性质观察得较慢。
值域给的 \(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 filename
FileOperations();
#endif
int _;
cin >> _;
while(_--) Traveller::main();
return 0;
}

浙公网安备 33010602011771号