cf804C(dfs染色)

题目链接: http://codeforces.com/problemset/problem/804/C

 

题意: 有一颗含有 n 个顶点的树, 第 i 个顶点上有 k 个冰激凌, 每个冰激凌的种类为 si . 现在要给所有定点上的冰激凌染色 , 要求相同种类的冰激凌染相同的颜色, 并且同一个顶点上的冰激凌要求染不同颜色.

注意: 同一个顶点中不会出现相同的冰激凌

 

思路: dfs染色

首先因该考虑最多需要多少中颜色, 然后再考虑怎么染色. 对于一种冰激凌, 如果确定了其染什么颜色, 那么在后面其他顶点中遇到这中冰激凌也直接染成这种颜色即可.

对于一种在其它顶点中用过的颜色, 若在当前顶点中没有用过, 那么可以将当前顶点中某个冰激凌染成这种颜色. 显然, 限制所需颜色种数的条件为 max(ki), 并且最少需要的颜色种数即为: max(ki). 至于具体染色方案只需 dfs 一遍即可. dfs 过程为: 在当前顶点中, 对于之前染过色的冰激凌, 先给它染上同种颜色, 对于剩下的冰激凌, 依次选取当前最小的且当前顶点中没用过的颜色染上即可.

 

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <vector>
 4 #include <string.h>
 5 #include <map>
 6 using namespace std;
 7 
 8 const int MAXN = 3e5 + 10;
 9 vector<int> vt1[MAXN], vt2[MAXN];
10 map<int, int> vis;
11 int sol[MAXN];
12 
13 void dfs(int x, int pre){
14     // memset(vis, 0, sizeof(vis));用数组标记会tle
15     vis.clear();
16     for(int i = 0; i < vt1[x].size(); i++){
17         if(sol[vt1[x][i]]) vis[sol[vt1[x][i]]] = 1;//记录前面用过的颜色
18     }
19     int cnt = 0;
20     for(int i = 0; i < vt1[x].size(); i++){
21         if(sol[vt1[x][i]]) continue;
22         while(vis[++cnt]){};
23         sol[vt1[x][i]] = cnt;//将没有标记的冰激凌染上新颜色
24     }
25     for(int i = 0; i < vt2[x].size(); i++){
26         if(vt2[x][i] != pre) dfs(vt2[x][i], x);
27     }
28 }
29 
30 int main(void){
31     int n, m, k, x, y, ans = 1;
32     scanf("%d%d", &n, &m);
33     for(int i = 1; i <= n; i++){
34         scanf("%d", &k);
35         if(ans < k) ans = k;
36         while(k--){
37             scanf("%d", &x);
38             vt1[i].push_back(x);
39         }
40     }
41     for(int i = 1; i < n; i++){
42         scanf("%d%d", &x, &y);
43         vt2[x].push_back(y);
44         vt2[y].push_back(x);
45     }
46     dfs(1, -1);
47     printf("%d\n", ans);
48     for(int i  = 1; i <= m; i++){
49         if(sol[i]) printf("%d ", sol[i]);
50         else printf("1 ");
51     }
52     puts("");
53     return 0;
54 }
View Code

 

posted @ 2017-07-06 17:10  geloutingyu  阅读(532)  评论(0编辑  收藏  举报