题目链接: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 " , cnt); for(int i = 1 ; i <= m ; i++) { if(ans[i] == 0) { printf("1 "); } else { printf("%d " , ans[i]); } } printf(" "); return 0; }