CF 551 D.Serval and Rooted Tree 树形DP

传送门:http://codeforces.com/contest/1153/problem/D

思路:

这道题想了一天,突发奇想,就是维护每个点两个值,第几大和第几小,就可以有传递性了。

#include <bits/stdc++.h>

using namespace std;

#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef pair<int, int> pii;
const ll inff = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;

        const int maxn = 3e5+9;
        int a[maxn];
        vector<int>mp[maxn];
        int dp[maxn][2];
        int all = 0;
        void dfs(int u, int fa) {
            if(mp[u].size() == 0) dp[u][0] = dp[u][1] = 1, all++;
            else if(a[u] == 1) dp[u][0] = 0, dp[u][1] = inf;
            else if(a[u] == 0) dp[u][0] = inf, dp[u][1] = 0;

            for(int i=0; i<mp[u].size(); i++) {
                int v = mp[u][i];
                if(v == fa) continue;
                dfs(v, u);

                if(a[u] == 1) {
                    dp[u][1] = min(dp[v][1], dp[u][1]);
                    dp[u][0] += dp[v][0];
                }
                else {
                    dp[u][1] += dp[v][1];
                    dp[u][0] = min(dp[v][0], dp[v][1]);
                }
            }
        }

int main(){
        int n;
        scanf("%d", &n);
        for(int i=1; i<=n; i++) scanf("%d", &a[i]);
        for(int i=2; i<=n; i++) {
            int x;  scanf("%d", &x);
            mp[x].pb(i);
        }
        memset(dp, inf, sizeof(dp));
        dfs(1, 1);
       // cout<<" dp[5][1] = " <<dp[5][1]<<endl;
       // cout<<dp[1][0] << " , " << dp[1][1]<<endl;
        printf("%d\n", max(dp[1][0], all - dp[1][1] + 1 ));
        return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/ckxkexing/p/10757737.html