Day2-O-Coloring a Tree CodeForces-902B
You are given a rooted tree with n vertices. The vertices are numbered from 1 to n, the root is the vertex number 1.
Each vertex has a color, let's denote the color of vertex v by cv. Initially cv = 0.
You have to color the tree into the given colors using the smallest possible number of steps. On each step you can choose a vertex v and a color x, and then color all vectices in the subtree of v (including v itself) in color x. In other words, for every vertex u, such that the path from root to u passes through v, set cu = x.
It is guaranteed that you have to color each vertex in a color different from 0.
You can learn what a rooted tree is using the link: https://en.wikipedia.org/wiki/Tree_(graph_theory).
Input
The first line contains a single integer n (2 ≤ n ≤ 104) — the number of vertices in the tree.
The second line contains n - 1 integers p2, p3, ..., pn (1 ≤ pi < i), where pi means that there is an edge between vertices i and pi.
The third line contains n integers c1, c2, ..., cn (1 ≤ ci ≤ n), where ci is the color you should color the i-th vertex into.
It is guaranteed that the given graph is a tree.
Output
Print a single integer — the minimum number of steps you have to perform to color the tree into given colors.
Examples
6
1 2 2 1 5
2 1 1 1 1 1
3
7
1 1 2 3 1 4
3 3 1 1 1 2 3
5
(图片好像挂了,具体Note可以看一下原题)
思路:从树根1开始,层序遍历涂色,DFS+BFS,代码如下:
const int maxm = 1e4+10; int color[maxm], now[maxm], n, tmp, t; vector<int> son[maxm]; void dfs(int i, int col) { for(auto j : son[i]) dfs(j, col); now[i] = col; } int main() { scanf("%d", &n); for (int i = 2; i <= n; ++i) { scanf("%d", &tmp); son[tmp].push_back(i); } for (int i = 1; i <= n; ++i) scanf("%d", &color[i]); queue<int> q; q.push(1); while(!q.empty()) { tmp = q.front(), q.pop(); if(color[tmp] != now[tmp]) { dfs(tmp, color[tmp]); ++t; } for(auto i : son[tmp]) q.push(i); } printf("%d\n", t); return 0; }
DFS版层序,代码如下:
const int maxm = 1e4 + 10; int color[maxm], now[maxm], n, tmp, t; vector<int> son[maxm]; void dfs1(int i, int col) { for(auto j : son[i]) dfs1(j, col); now[i] = col; } void dfs2(int i) { if(color[i] != now[i]) { dfs1(i, color[i]); ++t; } for(auto j : son[i]) dfs2(j); } int main() { scanf("%d", &n); for (int i = 2; i <= n; ++i) { scanf("%d", &tmp); son[tmp].push_back(i); } for (int i = 1; i <= n; ++i) scanf("%d", &color[i]); dfs2(1); printf("%d\n", t); return 0; }
看到网上聚聚的解析,都不用建树搜索,直接判断某节点是否与其父节点目标颜色一致,若不一致一定需要额外一次染色,代码如下:
const int maxm = 1e4 + 10; int color[maxm], now[maxm], father[maxm], n, t; int main() { scanf("%d", &n); for (int i = 2; i <= n; ++i) scanf("%d", &father[i]); for (int i = 1; i <= n; ++i) scanf("%d", &color[i]); for (int i = 1; i <= n; ++i) if(color[i] != color[father[i]]) ++t; printf("%d\n", t); return 0; }