没有上司的舞会题解

    科技2022-07-14  127

    题目描述

    Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起参加宴会。

    输入格式

    第一行一个整数N。(1≤N≤6000)

    接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128≤Ri≤127)

    接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。

    最后一行输入0,0。

    输出格式

    第1行:输出最大的快乐指数。

    样例

    样例输入

    7 1 1 1 1 1 1 1 1 3 2 3 6 4 7 4 4 5 3 5

    样例输出

    5

    题解:

    我们定义一下dp[i][0]表示以i为根的子树的最大气氛值,且i不参加

    dp[i][1]表示以i为根的子树的最大气氛值,且i参加

    对于每一个人来说,他参加的前提是他的直接上司不参加,换句话说,对于每个人来说,他参加的前提是每一个直接下属不参加;

    所以

    dp[i][0]= ∑ \sum max(dp[son][0],dp[son][1])

    dp[i][1]= ∑ \sum max(0,dp[son][0])+max(0,v[i]);

    其中son表示该节点的子节点;

    代码

    #include<bits/stdc++.h> #define max(x,y) x>y?x:y using namespace std; vector<int> v[6005]; int a[6005]={}; int dp[6005][2]={}; int n,sum; int f[6005]={}; void DP(int x){ dp[x][0]=0; dp[x][1]=a[x]; for(int i=0;i<v[x].size();i++){ int y=v[x][i]; DP(y); dp[x][0]+=max(dp[y][0],dp[y][1]); dp[x][1]+=dp[y][0]; } } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); v[y].push_back(x); f[x]=1; } for(int i=1;i<=n;i++){ if(!f[i]){ sum=i; break; } } DP(sum); printf("%d",max(dp[sum][1],dp[sum][0])); return 0; }
    Processed: 0.011, SQL: 8