P1352

· · 个人记录

题目描述

某大学有 n 个职员,编号为1…n。

他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。

现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数 ri,但是呢,如果某个职员的直接上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。

所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

这题不多做解释,都在代码里了

#include<bits/stdc++.h>
using namespace std;
const int maxn=6005;
int n,f[maxn][2],g[maxn]={0},h[maxn];
vector<int> son[maxn];//动态数组 
inline int read()
{
    int x=1,y=0;
    char z=getchar();
    while(z<'0'||z>'9')
    {
        if(z=='-')
        x=-1;
        z=getchar();
    }
    while(z>='0'&&z<='9')
    {
        y=y*10+z-'0';
        z=getchar();
    }
    return x*y;
}//快读代码 
void dp(int x)
{
    f[x][0]=0;//如果x不去,那么快乐值为0
    f[x][1]=h[x];//如果x去,那么快乐值为h[x]
    for(int i=0;i<son[x].size();i++)
    {
        int y=son[x][i];//y为x的下属
        dp(y);//继续查,直到查到它没有下属为止(即该职员没有下属)
        f[x][0]+=max(f[y][0],f[y][1]);//如果x不去,那么快乐值就加上他的下属去或不去中的最大值
        f[x][1]+=f[y][0];//如果x去,那么快乐值就加上他的下属不去的快乐值
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    h[i]=read();
    for(int i=1;i<=n-1;i++)
    {
        int x,y;
        x=read();
        y=read();
        son[y].push_back(x);//son存y的下属,即x
        g[x]=1;//如果x有下属,g[x]就存1,否则g[x]存的就是零,即x为最大的上司,他没有上司了 
    }
    int root;
    for(int i=1;i<=n;i++)
    if(!g[i])
    {
        root=i;//root存最大上司的编号
        break;//查到了就退出
    }
    dp(root);//从最大上司开始查
    cout<<max(f[root][0],f[root][1]);//输出x去和x不去中快乐值较大的那个,就是最终答案 
    return 0;
}

自认为解释的还是比较通俗易懂