题目链接:http://codeforces.com/contest/805/problem/E
题意:你有n个节点,这个n个节点构成一棵树。每个节点拥有有si个类型的ice,同一个节点的ice互相连边构成完全图。对于拥有相同ice的节点u,v,在树上一定相邻。求将ice构成的图染色,相邻点不可同色的最小颜色数以及方案。
题解:就是简单的dfs一遍现将首个节点对应的ice赋予不同的数字,记录一下ice对应的颜色,再dfs到下个树节点,现将
已经染过色的ice存一下然后再遍历一遍没染过色的ice给他赋予一个符合条件的最小的值具体方法就是用vector存下染过
色的ice然后从小到大排序一下,sta表示vector下表,now表示颜色同时递增知道now!=vector[sta]是赋予这个ice颜色
同时更新一下cnt(cnt表示总共又多少种颜色)
#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M = 3e5 + 10;
set<int>s[M];
set<int>::iterator it;
vector<int>vc[M];
int ans[M] , cnt;
void dfs(int pos , int pre) {
vector<int>used;
if(pre == -1) {
for(it = s[pos].begin() ; it != s[pos].end() ; it++) {
ans[(*it)] = ++cnt;
}
}
else {
for(it = s[pos].begin() ; it != s[pos].end() ; it++) {
if(ans[(*it)]) {
used.push_back(ans[(*it)]);
}
}
int L = used.size();
sort(used.begin() , used.end());
int sta = 0 , now = 1;
for(it = s[pos].begin() ; it != s[pos].end() ; it++) {
if(!ans[(*it)]) {
while(sta < L) {
if(now == used[sta]) now++ , sta++;
else break;
}
ans[(*it)] = now++;
}
cnt = max(cnt , now - 1);
}
}
int len = vc[pos].size();
for(int i = 0 ; i < len ; i++) {
int v = vc[pos][i];
if(v != pre) {
dfs(v , pos);
}
}
}
int main() {
int n , m , num , x;
scanf("%d%d" , &n , &m);
for(int i = 1 ; i <= n ; i++) {
scanf("%d" , &num);
for(int j = 0 ; j < num ; j++) {
scanf("%d" , &x);
s[i].insert(x);
}
}
int u , v;
for(int i = 0 ; i < n - 1 ; i++) {
scanf("%d%d" , &u , &v);
vc[u].push_back(v);
vc[v].push_back(u);
}
memset(ans , 0 , sizeof(ans));
cnt = 0;
dfs(1 , -1);
cnt = max(1 , cnt);
printf("%d\n" , cnt);
for(int i = 1 ; i <= m ; i++) {
if(ans[i] == 0) {
printf("1 ");
}
else {
printf("%d " , ans[i]);
}
}
printf("\n");
return 0;
}