P1352 没有上司的舞会

一道树形DP的入门题
前置知识:链式前向星,\(dfs\)

int head[N],nex[N],ver[N],tot;
void add(int x,int y){
    ver[++tot]=y;
    nex[tot]=head[x];
    head[x]=tot;
}

树形DP的主要实现形式是\(dfs\),\(dp_{0/1}\)代表:是否选择当前这个节点
一般对于是否选择节点类的树形DP有基础转移方程:
\(\begin{cases} dp[i][0]=dp[j][1]j为i的子节点\\dp[i][1]=max/min(dp[j][1],dp[j][0]) j为i的子节点\end{cases}\)
当然对于DP来说,当然需要具体问题具体分析(bushi

对于本题来说,对于每个直系上司参加,那么下属不参加;直系上司不参加,下属可参加可不参加,那么可以得到转移方程为:
\(\begin{cases} dp[i][1]+=dp[j][0]j为i的子节点\\dp[i][0]+=max(dp[j][1],dp[j][0]) j为i的子节点\end{cases}\)
因此最终结果\(ans=max(dp[root][0],dp[root][1]) root为树根\)

Code

#include <bits/stdc++.h>
using namespace std;
const int N=6e3+10;
typedef long long ll;

int dp[N][2],a[N],n;
int head[N],nex[N],ver[N],tot;
int fa[N];
void add(int x,int y){
    ver[++tot]=y;
    nex[tot]=head[x];
    head[x]=tot;
}
void dfs(int x){
    dp[x][1]=a[x];
    for(int i=head[x];i;i=nex[i]){
        int y=ver[i];
        dfs(y);
        dp[x][0]+=max(dp[y][0],dp[y][1]);
        dp[x][1]+=dp[y][0];
    }
}
int main(){

    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<n;i++){
        int l,k;
        cin>>l>>k;
        add(k,l);
        fa[l]=k;
    }
    int root=1;
    while(fa[root]) root++;
    dfs(root);
    int ans=max(dp[root][0],dp[root][1]);
    cout<<ans<<endl;

    return 0;
}
posted @ 2021-12-14 16:30  Wraith-Fiee  阅读(31)  评论(0)    收藏  举报