[CF805E] Ice cream coloring(dfs,贪心)
题目链接:http://codeforces.com/contest/805/problem/E
题意:一棵树有n个点,每一个点相当于一个有si个点的完全图。现在希望给每一个点染色,并且整个图上相邻两个不同类型的冰淇淋颜色不一样,同时,假如确定了一个颜色,那么整棵树上的同类型冰淇淋都是一个颜色。问一个可行的染色方案。
思路:直接从一个点开始dfs,遇到一个节点遍历这个节点的子图,看看哪个颜色用过,哪个颜色没用。同时也看下哪个点之前有颜色了,哪个点之前没有颜色。然后就从左到右扫没用过的颜色,直接染色即可。
注意每次递归的时候,vis数组memset会TLE,所以事先存好出现的颜色,之后挨个点置零。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 const int maxn = 300300; 6 int n, m, rcnt; 7 int ret[maxn]; 8 bool vis[maxn]; 9 vector<int> ice[maxn]; 10 vector<int> G[maxn]; 11 12 void dfs(int u, int p) { 13 vector<int> tmp; 14 for(int i = 0; i < ice[u].size(); i++) { 15 int x = ice[u][i]; 16 if(ret[x]) { 17 tmp.push_back(x); 18 vis[ret[x]] = 1; 19 } 20 } 21 int cnt = 1; 22 for(int i = 0; i < ice[u].size(); i++) { 23 int x = ice[u][i]; 24 if(ret[x]) continue; 25 while(vis[cnt]) cnt++; 26 ret[x] = cnt++; 27 } 28 for(int i = 0; i < tmp.size(); i++) vis[ret[tmp[i]]] = 0; 29 for(int i = 0; i < G[u].size(); i++) { 30 int v = G[u][i]; 31 if(v == p) continue; 32 dfs(v, u); 33 } 34 } 35 36 int main() { 37 // freopen("in", "r", stdin); 38 int u, v; 39 while(~scanf("%d%d",&n,&m)) { 40 memset(ret, 0, sizeof(ret)); 41 memset(vis, 0, sizeof(vis)); 42 rcnt = 0; 43 for(int i = 1; i <= n; i++) { 44 int cnt, c; 45 ice[i].clear(); G[i].clear(); 46 scanf("%d", &cnt); 47 for(int j = 0; j < cnt; j++) { 48 scanf("%d", &c); 49 ice[i].push_back(c); 50 } 51 } 52 for(int i = 0; i < n-1; i++) { 53 scanf("%d%d",&u,&v); 54 G[u].push_back(v); 55 G[v].push_back(u); 56 } 57 dfs(1, 0); 58 int p = 0; 59 for(int i = 1; i <= m; i++) { 60 if(!ret[i]) ret[i] = 1; 61 p = max(p, ret[i]); 62 } 63 printf("%d\n", p); 64 for(int i = 1; i <= m; i++) { 65 printf("%d%c", ret[i], i==m?'\n':' '); 66 } 67 } 68 return 0; 69 }