codeforces

链接:https://codeforces.com/contest/1153/problem/D
思路:令dp[u]表示u的子树中传上来的数是第k大的数,那么如果边是min,dp[u] = sum{dp[v]}, 如果是max,dp[u] = min{dp[v]}, 最后k - dp[1] + 1就是答案。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

using namespace std;

const int maxn = 3e5 + 5;
int f[maxn];
int ok[maxn];
int n, k;
vector<int> G[maxn];
int dp[maxn];
int deg[maxn];

void (int u, int fa){
if(ok[u] == 1 && deg[u]) dp[u] = 1e9;
for(auto &v : G[u]){
if(v == fa) continue;
dfs(v, u);
if(ok[u] == 0) dp[u] += dp[v];
else dp[u] = min(dp[u], dp[v]);
}
}

int main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;

for (int i = 1; i <= n; ++i) {
cin >> ok[i];
}

for (int i = 2; i <= n; ++i) {
cin >> f[i];
G[i].emplace_back(f[i]);
G[f[i]].emplace_back(i);
deg[f[i]]++;
}
for(int i = 1; i <= n; i++) if(!deg[i]) dp[i] = 1, k++;
dfs(1, 0);
cout << k - dp[1] + 1 << 'n';
return 0;
}