Solution
太菜了,看了雨巨的题解才发自己读错题了 自闭了一天
题目提到如果我们选择i点
i点到根的链上(包括节点i与根)所有与节点i距离小于k[i]的点都会变黑
那么我们就可以考虑从叶子开始取,因为取非叶子节点永远无法将叶子节点染黑
这样显然就可以用dfs递归从叶子往根染黑
其次,我们发现从叶子节点往上的点可能会因为选取叶子节点而被染黑
但是被染黑不代表就不取,我们可以简单的运用一个等价替换的思想:
考虑图上这种情况,显然权值为3这个点我们一定要取,而它的父亲节点是B权值为1,显然不用取
但是呢,我们可以转换思路,把权值3 - 1赋予给它的父亲节点,取个max即可 a[fa] = max(a[fa], a[u] - 1)
这样的话,我们从下往上,当dp[u] 为 0, 证明下面的节点无法把它包括,需要将这个点染黑
否则, 一直取max往上转移到根节点
Code
#pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long long LL; const int N = 1e5 + 5; const ll mod = 7; const int DEG = 20; const double PI = acos(-1.0); const double eps = 1e-10; const ll inf = 1e18; static auto faster_iostream = []() { std::ios::sync_with_stdio(false); // turn off sync std::cin.tie(nullptr); // untie in/out streams return 0; }(); int a[N], dp[N]; int ans; vector<int> G[N]; void dfs(int u, int par){ for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; dfs(v, u); a[u] = max(a[u], a[v] - 1); dp[u] = max(dp[u], dp[v] - 1); } if(!dp[u]){ dp[u] = a[u]; ans++; } } int main(){ int n; cin >> n; for(int i = 2; i <= n; i++){ int u; cin >> u; G[u].push_back(i); } for(int i = 1; i <= n; i++){ cin >> a[i]; } ans = 0; dfs(1, -1); cout << ans << "\n"; return 0; }