CodeForces - 1153D Serval and Rooted Tree(树形dp)
题目大意
给你一棵以1为根的树,你可以在叶子结点放1-叶子结点数量的数字,每个数字只能用一次,父节点有的对子节点取min,有的取max,问根结点的最大值。
解题思路
考虑最下层的父节点,如果是max,那么在所有子节点中选一个放比较大的数,其他放比较小的数就行了,如果是min,那么就要放一连串比较大的数结果才比较大。然后再往上考虑,发现max就是取所有子节点包含的最少的结点数那一个量,而min则是将所有子节点包含的数量相加(这里的数量指的是取min和max之后的数量,不是树中的数量)。
代码
const int maxn = 3e5+10;
const int maxm = 2e3+10;
int n, cnt, state[maxn];
vector<int> e[maxn];
int dfs(int u) {
if (e[u].empty()) {
++cnt;
return 1;
}
if (state[u]) {
int minn = INF;
for (auto v : e[u]) minn = min(minn, dfs(v));
return minn;
}
else {
int sum = 0;
for (auto v : e[u]) sum += dfs(v);
return sum;
}
}
int main() {
cin >> n;
for (int i = 1; i<=n; ++i) cin >> state[i];
for (int i = 2, a; i<=n; ++i) {
cin >> a;
e[a].push_back(i);
}
int ans = dfs(1);
cout << cnt-ans+1 << endl;
return 0;
}