传送门:http://codeforces.com/contest/902/problem/B
本题是一个关于“树”的问题。
有一棵n个结点的有根树,结点按照1~n编号,根结点为1。cv为结点v的色号,初始化为0。每一步选定一个结点v和一个色号x,于是v和v的所有后代结点均被染色,色号为x。
给定一个色号表{cv|v=1,2,...,n},满足1≤cv≤n,其中cv是结点v应该被染成的色号。求完成染色的最小操作步数。
注意到,若对结点v染色,色号为x,则v和v的所有后代结点均被染色,色号也为x。于是,应从根结点开始染色。设当前结点为v,v的子结点构成的集合为S(v),则对S(v)中的每一个结点u,若有cu≠cv,则对结点u重新染色,色号为cu。
则最终的答案为$ans=1+\sum_{v=1}^{n}{card\{u|u\in S,c_u\ne c_v\}}$。可通过DFS实现。参考程序如下:
#include <bits/stdc++.h> using namespace std; #define MAX_N 10001 int c[MAX_N]; bool vis[MAX_N]; vector<int> adjvex[MAX_N]; int ans = 1; void dfs(int v) { vis[v] = true; for (int i = 0; i < adjvex[v].size(); i++) { int u = adjvex[v][i]; if (!vis[u]) { if (c[u] != c[v]) ans++; dfs(u); } } } int main(void) { int n; scanf("%d", &n); for (int i = 2; i <= n; i++) { int p; scanf("%d", &p); adjvex[i].push_back(p); adjvex[p].push_back(i); } for (int i = 1; i <= n; i++) scanf("%d", &c[i]); dfs(1); printf("%d\n", ans); return 0; }