[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 }

 

posted @ 2017-05-15 20:25  Kirai  阅读(198)  评论(0编辑  收藏  举报