zoukankan      html  css  js  c++  java
  • P1352 没有上司的舞会

    题目描述:

      传送门

    题解思路:

    首先题目中发明确告诉了是一棵树,所以在输入数据后应该构建一棵树来储存这些数据。

    这是一道非常经典的树形dp问题,对每个结点dp[i][0]表示不邀请这个员工,其子树达到的最大快乐值,dp[i][1]表示邀请i员工其子树达到的最大值,对于每个结点的状态应该从这两方面去考虑。
    dp[i][0]=(i的全部员工的max(dp[u][1],dp[u][0)相加,也就是其子员工来或不来的最大快乐值。
    dp[i][1]=(i的全部员工的dp[u][0相加,也就是其子员工都不能不来的最大快乐值。
    从根结点开始dp,最终结果就是max(dp[root][0],dp[root][1])

    题目代码

    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define INF 1000000
    
    int n=0;
    int root=-1; 
    int r[6005];
    int p[6005]={0};        //专门用于找根节点 
    int flag[6005]={0};        //flag[i]判断结点i是否参加聚会 
    int dp[6005][2];
    struct node{        //树的结点 
        int size;
        int c[200];        //保存子节点的编号     c数组要开的大一点 防止不够 
    };
    node dd[6000];
    void dfs(int i){   
        dp[i][1]=r[i];   //i参加聚会 把自己的快乐值先加上 
     
    for(int j=0;j<dd[i].size;j++){   int son=dd[i].c[j];    //找i的孩子 if(son>0){ dfs(son); dp[i][0]+=max(dp[son][0],dp[son][1]);  //若i不参加聚会,则i的孩子们有两种选择 dp[i][1]+=dp[son][0];  //i参加聚会 则i的孩子无法参加 } } } int main(){ cin>>n; for(int i=1;i<=n;i++){ cin>>r[i]; } for(int i=1;i<=n-1;i++){    //用结构体数组来存树 int a,b; cin>>a>>b; //b是上司 dd[b].c[dd[b].size++]=a; p[a]=1; //代表a不是根 } for(int i=1;i<=n;i++){ if(p[i]==0){ root=i; //找到根节点 break; } } for(int i=1;i<=n;i++){ dp[i][0]=0; dp[i][1]=0; } dfs(root); cout<<max(dp[root][0],dp[root][1]);//注意dp[root][1]在dfs中已经加过r[root] return 0; }

    关于树形dp的一些解析和题目:

      传送门

  • 相关阅读:
    (4) 编译 Android-5.0 源码
    (3) 下载 Android-5.0 源码
    (2) 搭建 Android 系统开发环境
    npm 安装 --save-dev 与 --save的使用与区别
    一点目标
    AcWing 875. 快速幂
    Codeforces Round #604 (Div. 2)
    2019年安徽大学ACM/ICPC实验室新生赛(公开赛)D 不定方程
    C语言黑与白问题
    AcWing 92. 递归实现指数型枚举
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12889609.html
Copyright © 2011-2022 走看看