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 }
我就是我,颜色不一样的烟火 --- geloutingyu