1. 程式人生 > >Codeforces Round #551 (Div. 2) D 樹形dp

Codeforces Round #551 (Div. 2) D 樹形dp

include 數量 == namespace tor force ace 計算 我們

https://codeforces.com/contest/1153/problem/D

題意

一顆有n個點的數,每個點a[i]為0代表取子節點的最小,1代表取最大,然後假設樹上存在k個葉子,問你如何將1~k分配給葉子節點使得根節點最大

題解

  • 實際上最後只有一個值能到達根,我們需要計算沒用的葉子節點數量
  • min:相當於將子節點葉子數量相加
  • max:相當於將子節點葉子數量取最小
  • ans=葉子數-sz[1]+1

代碼

#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
vector<int>G[MAXN];
int a[MAXN],Sz[MAXN],n,v,lt;
void dfs(int u,int fa){
    int son=0;
    for(auto v:G[u]){
        if(fa==v)continue;
        son++;
        dfs(v,u);
        Sz[u]+=Sz[v];
    }
    if(son==0){lt++;Sz[u]=1;return;}
    if(a[u]==1){
        Sz[u]=n;
        for(auto v:G[u]){
            if(fa==v)continue;
            Sz[u]=min(Sz[v],Sz[u]);
        }
    }
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int u=2;u<=n;u++){
        scanf("%d",&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0);
    cout<<lt-Sz[1]+1;
}

Codeforces Round #551 (Div. 2) D 樹形dp