
题意
给定一个1 到 n 的正方形,有n - 1个关系,每个关系是两个正方形相邻,
问从1号正方形开始染色,每个正方形周围的颜色和本身不相同,问最多需要多少种颜色
思路
PS:先开始想着bfs搜索,然后暴力枚举前面没用过的颜色,先用小的,结果T了,很现实。
转换思路, 分析枚举当前的结点时,这个结点的颜色收到父亲结点,和祖父结点的影响。例如此图

当枚举3号结点时它就受到它父亲结点(1号结点)的影响,由于3号结点没有祖父结点,所以不管。
再枚举到2号结点时,他就不能和(1, 3结点)的颜色相同。再到5号结点时,他不能和(1,3,2)的颜色相同。
现在问题来了,怎么我们记录不和1,3相等容易,就是父亲结点和祖父结点不能相等,那么这个2怎么处理?
就要用一个变量num初始为1,开始一直变大,当与父亲结点相连的儿子结点时,让num一直增大,
取第一个不与父亲和祖父结点相同的颜色,这样保证这些兄弟之间的颜色不同,也保证了与父亲和祖父的颜色不同。
AC代码
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 2e5 + 5;
vector<int> g[maxn];
int val[maxn];
int fa[maxn];
queue<int> q;
void init(int n){
for (int i = 1; i <= n; ++i){
g[i].clear();
val[i] = 0;
fa[i] = i;
}
}
void bfs(int n){
while (!q.empty()) q.pop();
q.push(1);
val[1] = 1;
fa[1] = 1;
int mx = 0;
while (!q.empty()){
int now = q.front(); q.pop();
mx = max(mx, val[now]);
int num = 1, len = g[now].size();
for (int i = 0; i < len; ++i){
int v = g[now][i];
if (val[v]) continue;
while (val[now] == num || val[fa[now]] == num) num++;
val[v] = num++;
fa[v] = now;
q.push(v);
}
}
printf("%d\n", mx);
for (int i = 1; i <= n; ++i){
if (i < n) printf("%d ", val[i]);
else printf("%d\n", val[i]);
}
}
void solve(){
int n, u, v;
scanf("%d", &n);
init(n);
for (int i = 0; i < n - 1; ++i){
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
bfs(n);
}
int main(){
solve();
return 0;
}