C - ThREE

构造一个数列 $(i,j)$如果树上距离为$3$ 那么 $a[i]*a[j]=3k$或者$a[i]+a[j]=3k$

对于一个点$i$值不为$3$的倍数为$x$与他不发生关系的为距离$+1,+2,+4,+5,-1,-2,-4,-5$的点的的值都为$x$,(距离$(3,-3)$设置成$3-x$)发现距离为$(4,1),(-4,5),(1,-2)$这些点对不成立,那我只要保证距离相减不会出现$3$就好,那么让相隔距离为$2$。即距离为$2,4,-2,-4$的点值为$x$,其余为$2-x$。

这样就可以给树上染色成奇数点和偶数点。只要将奇数点塞进$mod=1$,偶数点塞进$mod=2$。

保证了相同数之间互不干扰,比如距离为(1,2,3,4,5)的点的值为$x,2-x,x,2-x,x$。距离为$3或1$的加起来一定为3。因为$3k$怎么给都$ok$。所以把剩余点给$3k$。

$n/2>=n/3$ 一定够塞的

代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
const int mod = 1e9 + 7;

vector<int> graf[N];
vector<int> h[2];
void dfs(int x, int y = 0, int d = 0)
{
h[d].push_back(x);
for (int v : graf[x])
if (v != y)
dfs(v, x, d ^ 1);
}
int ans[N];
int main()
{
int n;
scanf("%d", &n);
for (int i = 1; i < n; i++)
{
int a, b;
scanf("%d%d", &a, &b);
graf[a].push_back(b);
graf[b].push_back(a);
}
dfs(1, 0);
vector<int> p[3];
for (int i = 1; i <= n; ++i)
p[i % 3].push_back(i);

for (int c = 1; c <= 2; ++c)
{
bool did = true;
for (int d = 0; d < 2; d++)
if (h[d].size() >= p[c].size())
{
for (int x : p[c])
{
ans[h[d].back()] = x;
h[d].pop_back();
}
did = true;
break;
}
//assert(did);
}
for (int i = 1; i <= n; ++i)
if (ans[i] == 0)
{
ans[i] = p[0].back();
p[0].pop_back();
}
for (int i = 1; i <= n; ++i)
printf("%d ", ans[i]);
printf("\n");
}