[CF1153D] Serval and Rooted Tree - 树形dp

Description

\(n\) 个节点以 \(1\) 为根的一棵树,每个非叶子节点都有一个操作 \(\max\)\(\min\),表示这个节点中的值应该分别等于其子节点中所有值的最大值或最小值。假设树上有 \(k\) 个叶节点,你可以将每个叶节点填上 \([1,k]\) 的数字,且每个数字只使用一次,求根节点的最大值。

Solution

\(f[p]\) 表示 \(p\) 在其子树叶子结点中的权值排名的最大值

对于叶子结点,\(f=1\)

对于 \(\min\) 结点,\(f[p]=\sum_{p\to q} f[q]\)

对于 \(\max\) 结点,\(f[p]=\min_{p \to q} f[q]\)

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;

int a[N],f[N],n,t1,t2,v[N],k;
vector <int> g[N];

void dfs(int p) {
    int fg=0;
    v[p]=1;
    if(a[p]) f[p]=n+1;
    else f[p]=0;
    for(int q:g[p]) if(!v[q]) {
        ++fg;
        dfs(q);
        if(a[p]) f[p]=min(f[p],f[q]);
        else f[p]+=f[q];
    }
    if(fg==0) f[p]=1, ++k;
}

signed main() {
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=2;i<=n;i++) {
        cin>>t1;
        g[t1].push_back(i);
        g[i].push_back(t1);
    }
    dfs(1);
    cout<<k+1-f[1];
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12913172.html