没有上司的舞会(简单树形dp)

描述
Ural 州立大学的校长正在筹备学校的 80 周年纪念聚会。由于学校的职员有不同的职务级别,可以构成一棵以校长为根的人事关系树。每个资源都有一个唯一的整数编号,从 1 到 N 编号,且对应一个参加聚会所获得的欢乐度。为使每个职员都感到快乐,校长设法使每个职员和其直接上司不会同时参加聚会。
你的任务是设计一份参加聚会者的名单,使总欢乐度最高。
输入
第一行是一个整数 N ;
接下来 N 行对应 N 个职员的欢乐度,第 ii行的一个整数为第i 个职员的欢乐度pi
接着是学校的人事关系树,每一行格式为 L K ,表示第 K 个职员是第 L 个职员的直接上司,输入以 0 结束。
输出
输出参加聚会者获得的最大欢乐度。
样例输入
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
样例输出
5
提示
对于 100% 的数据,1≤N≤6000,−128≤pi≤127

简单树形dp,都不用怎么说了吧

f[i][0/1]f[i][0/1]表示以ii为根的子树,当前这个点选还是不选的的最大值

很容易得到递推方程

f[u][0]=Σmax(f[v][0],f[v][1])(vson[u])f[u][0]=Σmax(f[v][0],f[v][1])(v∈son[u])

f[u][1]=Σf[v][0]f[u][1]=Σf[v][0];

直接递归求解

#include<bits/stdc++.h>
using namespace std;
inline int read(){
    char ch=getchar();
    int res=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res*f;
}
int f[6005][2],n,m,fa[6005],a[6005],adj[12005],nxt[12005],to[12005],cnt;
inline void addedge(int u,int v){
    nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
}
inline void dfs(int u,int fa){
    f[u][0]=0,f[u][1]=a[u];
    for(int e=adj[u];e;e=nxt[e]){
        int v=to[e];
        if(v==fa)continue;
        dfs(v,u);
        f[u][0]+=max(f[v][0],f[v][1]);
        f[u][1]+=f[v][0];
    }
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<n;i++){
        int u=read(),v=read();
        addedge(v,u);fa[u]=v;
    }
    read(),read();
    int p;
    for(int i=1;i<=n;i++)if(!fa[i]){p=i;break;}
    dfs(p,0);
    cout<<max(f[p][0],f[p][1])<<'
';
}
原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366417.html