没有上司的舞会

题目大意:

Ural大学有N名职员,编号为1~N。他们的关系就像一棵以校长为根的树,父节点就是子节点的直接上司。每个职员有一个快乐指数,用整数 H_i 给出,其中 1≤i≤N。现在要召开一场周年庆宴会,不过,没有职员愿意和直接上司一起参会。在满足这个条件的前提下,主办方希望邀请一部分职员参会,使得所有参会职员的快乐指数总和最大,求这个最大值。

解题思路:

树形dp
f[x][0]表示从以x为根的子树中邀请一部分职员参会,并且x不参加舞会时快乐指数总和的最大值。
f[x][1]表示从以x为根的子树中邀请一部分职员参会,并且x参加舞会时快乐指数总和的最大值。
son[x]表示x的子节点集合

转移方程:
f[x][0]+=max(f[y][0],f[y][1]);
f[x][1]+=f[y][0];

Accepted Code:

#include
#include
#include
#include
using namespace std;
vector<int> son[10005];
int f[10005][2],v[10005],h[10005],n,root;


inline void read(int &f) {
    char c=getchar(); int ag=1; f=0;
    while(!isdigit(c)) {if (c=='-') ag=-1; c=getchar();}
    while(isdigit(c)){f=(f<<3)+(f<<1)+c-48;c=getchar();}
    f*=ag; return;
}
void write(int x) {
    if (x>9) write(x/10); putchar(x%10+48); return;
}
void writeln(int x) {
    write(x); putchar('\n'); return;
}


inline void init() {
    read(n); int x,y;
    for (int i=1;i<=n;i++) read(h[i]);
    for (int i=1;i1; son[y].push_back(x);
        //v[x]=1/0表示x有/无父节点
    }
    read(x); read(y);
    for (int i=1;i<=n;i++)
        if (!v[i]) {//i没有父节点
            root=i;//找到第一个没有父节点的就是这棵树的根
            break;
        }
}
void Dp(int x) {
    f[x][0]=0;
    f[x][1]=h[x];
    for (int i=0;iint y=son[x][i];
        Dp(y);
        f[x][0]+=max(f[y][0],f[y][1]);
        f[x][1]+=f[y][0];
    }
}
int main() {
    init();
    Dp(root);
    write(max(f[root][0],f[root][1]));
}

你可能感兴趣的:(树形dp,dp)