AT5759 ThREE 题解
solution
一道比较好的构造题。
距离为三的点对至少满足 \(p_i + p_j\) 和 \(p_i \times p_j\) 其中一个为 \(3\) 的倍数。
不妨考虑什么时候距离为 \(3\) 的点对两个条件都不满足。
把总的数分为三类:
A: \(p_i \equiv 0~(mod~ 3)\)
B: \(p_i \equiv 1~(mod~ 3)\)
C: \(p_i \equiv 2~(mod~ 3)\)
发现只有 \(p_i \equiv 1~(mod~ 3)\), \(p_j\equiv 1 ~(mod~3)\) 或者 \(p_i \equiv 2~(mod~ 3)\), \(p_j\equiv 2 ~(mod~3)\) 这会同时不满足。
就考虑构造方案让这两种情况都不发生。
构造方案:对树进行黑白染色。
设黑色点的数量为 \(x\), 白色点的数量为 \(y\)
- 当 \(x > \lfloor \frac{n}{3} \rfloor\), \(y > \lfloor \frac{n}{3} \rfloor\) 时。
把 \(B\) 全为白点,\(C\) 全为黑点,显然,\(B, C\) 类肯定会全部被染完,剩下 \(A\) 类随便分就好了。
- 当 \(x \leq \lfloor \frac{n}{3} \rfloor\)
此时黑点全为 C 类,此时黑点会全被用完,剩下的全为白点就好了。
- 当 \(y \leq \lfloor \frac{n}{3} \rfloor\)
此时白点全为 C 类,此时白点会全被用完,剩下的全为黑点就好了。
所以一定可以构造出一组解满足条件。
code
/*
work by: Ariel_
Knowledge:
Time:
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXM = 4e5 + 5, MAXN = 2e5 + 5;
int read() {
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();}
return x * f;
}
int n, col[MAXN], cnt_1, cnt_0, Ans[MAXN];
struct edge{int v, nxt;}e[MAXM];
int E, head[MAXN];
void add_edge(int u, int v) {
e[++E] = (edge){v, head[u]};
head[u] = E;
}
void dfs(int x, int fa) {
col[x] = col[fa] == 1 ? 0 : 1;
col[x] == 1 ? cnt_1++:cnt_0++;
for (int i = head[x]; i; i = e[i].nxt) {
int v = e[i].v;
if(v == fa) continue;
dfs(v, x);
}
}
int p_1 = 1, p_2 = 2, p_0 = 3;
int main(){
n = read();
for (int i = 1; i < n; i++) {
int u = read(), v = read();
add_edge(u, v), add_edge(v, u);
}
dfs(1, 1);
for (int i = 1; i <= n; i++) {
if(cnt_1 > n / 3 && cnt_0 > n / 3) {
if(col[i]) {
if (p_1 <= n) Ans[i] = p_1, p_1 += 3;
else Ans[i] = p_0, p_0 += 3;
}
else {
if (p_2 <= n) Ans[i] = p_2, p_2 += 3;
else Ans[i] = p_0, p_0 += 3;
}
}
else if(cnt_1 <= n / 3) {
if(!col[i]) {
if(p_1 <= n) Ans[i] = p_1, p_1 += 3;
else if(p_2 <= n) Ans[i] = p_2, p_2 += 3;
else Ans[i] = p_0, p_0 += 3;
}
else Ans[i] = p_0, p_0 += 3;
}
else if(cnt_0 <= n / 3){
if(col[i]) {
if(p_1 <= n) Ans[i] = p_1, p_1 += 3;
else if(p_2 <= n) Ans[i] = p_2, p_2 += 3;
else Ans[i] = p_0, p_0 += 3;
}
else Ans[i] = p_0, p_0 += 3;
}
}
for (int i = 1; i <= n; i++) printf("%d ", Ans[i]);
puts("");
return 0;
}