1. 程式人生 > >cf804C(樹_dfs染色)

cf804C(樹_dfs染色)

ring push 技術 ios img .com code 什麽 b-

題目鏈接: 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

cf804C(樹_dfs染色)