Codeforces Round #411 (Div. 2) E
题意:
有一棵树T有n个结点,有m种冰淇淋。T中每个结点有一些种类的冰淇淋,也有可能没有冰淇淋。拥有同一种冰淇淋的结点构成联通子图。没有冰淇淋的结点也构成联通子图。
现在创建一个图G,有m个结点,对应m种冰淇淋。如果有u,v两种冰淇淋同时出现在T的某个结点中,就在G中增加边uv。要给图G着色,使得相邻的点颜色不相同,且使用的颜色总数最少,求染色方案。
思路:
先说结论,我们只要搜索树中每一个结点,对于当前节点中未染色的点,贪心地使用尽可能小、而又不和当前的节点中已经使用过的颜色冲突的颜色来染即可。原因是题目中特殊条件:在树T中,拥有相同种类冰淇淋的结点构成联通子图。这样可以反证,当前贪心选择最小的颜色来染,一定不会在新图G中和它相邻结点的颜色发生冲突。
#include <bits/stdc++.h>
using namespace std;
const int mx = 3e5 + 10;
int n, m, ans = 0;
int color[mx];
int in[mx];
bool colored[mx], vis[mx];
vector<int> s[mx];
vector<int> t[mx];
vector<int> v1, v2;//待着色 已着色
void init(){
cin >> n >> m;
for(int i = 1; i <= n; i++){
int len; scanf("%d", &len);
if(len > ans) ans = len;
while(len--){
int tmp; scanf("%d", &tmp);
s[i].push_back(tmp);
}
}
for(int i = 1; i < n; i++){
int u, v;
scanf("%d %d", &u, &v);
t[u].push_back(v);
t[v].push_back(u);
}
}
void dfs(int u){
vis[u] = true;
v1.clear(); v2.clear();
for(int i = 0; i < s[u].size(); i++){
int tnode = s[u][i];
if(!color[tnode]) v1.push_back(tnode);
else {
v2.push_back(tnode);
colored[color[tnode]] = true;
}
}
int c = 1;
for(int i = 0; i < v1.size(); i++){
while(colored[c]) c++;
color[v1[i]] = c++;
}
for(int i = 0; i < v2.size(); i++){
colored[color[v2[i]]] = false;
}
for(int i = 0; i < t[u].size(); i++)
if(!vis[t[u][i]]) dfs(t[u][i]);
}
void solve(){
dfs(1);
if(!ans){
cout << 1 << endl;
for(int i = 1; i <= m; i++)
printf("1 ");
printf("\n");
}
else{
cout << ans << endl;
for(int i = 1; i <= m; i++)
printf("%d ", max(color[i], 1));
printf("\n");
}
}
int main()
{
init();
solve();
return 0;
}
问题: 用bfs会有什么问题吗?
[Wèntí: Yòng bfs huì yǒu shé me wèntí ma?]
problem:
Is there any problem with bfs?
Is there any problem with bfs?