CF780C_Andryusha and Colored Balloons
题目概述
n个节点n-1条边的无向图,保证连通(就是一棵树),要给所有点染色,图中任意3个直接连通的点所用的颜色不能相同,n最多2*1e5个点,要求用最少的颜色种类来染色,输出所有点的颜色情况,任意一种即可。
解题思路
第一点——找到颜色种类K
其实最少用多少种颜色是好求的,因为一个点周围的颜色(也就是所连的点的颜色)都是不能相同,再加上这个点自己,所以我们可以先求出来哪个点所连的点数最多,再加上它自己就是最少的颜色种类,因为相当于最难满足的我们满足了,其他的点最好满足了。
第二点——染色
我们可以在遍历整个图的过程中就给点进行染色,这个时候我们可以采用一种染色盘的方法。
例如:
样例二的图
根据第一点我们可以求出最少的颜色种类是5,那么好,我们可以这5种颜色制作成一个颜色盘(就是循环数组0,1,2,3,4,输出的时候加一即可),就像是时钟那样。
x = 1,c = 0
我们从节点1开始,染色0,那么第一个与1相邻的颜色就是(c+1)%k,但是这样推下去不能和节点x的pre节点(父节点)的颜色相同,在代码中观察。
vector<int>col(n + 1);
col[0] = k;
vector<bool>vis(n + 1);
auto dfs = [&](auto&& dfs, int x, int c,int pre)->void {
vis[x] = 1;
col[x] = c;
for (auto& y : g[x]) {
if (vis[y]) continue;
c = (c + 1) % k;
while(c==col[pre]) c = (c + 1) % k;
dfs(dfs, y, c,x);
}
};
dfs(dfs, 1, 0, 0);
dfs的搜索图如下
点的先后顺序的问题,有些点的颜色可能有所不同,但都是满足上述点与点之间的性质的,1的pre记录的是0,是一个不存在的点,不需要再特判点了,写起来比较简洁。
code
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n;
m = n - 1;
int k = 0;
vector<vector<int>>g(n + 1);
while (m--) {
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
//找最大的连接数
k = max(k, (int)g[a].size());
k = max(k, (int)g[b].size());
}
//加上哪个点它自己
k++;
//记录点的颜色
vector<int>col(n + 1);
col[0] = k;
//记录点有没有被搜索过
vector<bool>vis(n + 1);
auto dfs = [&](auto&& dfs, int x, int c,int pre)->void {
vis[x] = 1;
col[x] = c;
for (auto& y : g[x]) {
if (vis[y]) continue;
c = (c + 1) % k;
while(c==col[pre]) c = (c + 1) % k;
dfs(dfs, y, c,x);
}
};
dfs(dfs, 1, 0, 0);
cout << k << endl;
for (int i = 1; i <= n; i++) cout << col[i] + 1 << " ";
return 0;
}