zoukankan      html  css  js  c++  java
  • P1352 没有上司的舞会——树形DP入门

    P1352 没有上司的舞会

    题目描述

    某大学有N个职员,编号为1~N。他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri,但是呢,如果某个职员的上司来参加舞会了,那么这个职员就无论如何也不肯来参加舞会了。所以,请你编程计算,邀请哪些职员可以使快乐指数最大,求最大的快乐指数。

    输入输出格式

    输入格式:

    第一行一个整数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
    0 0
    
    输出样例#1: 复制
    5

    树形DP——DFS版

    #include<bits/stdc++.h>
    
    #define N 6005
    using namespace std;
    
    int n,r[N],dp[N][2],tot,head[N];
    struct node{
        int to,next;
    }e[N];
    
    bool v[N];
    void add(int u,int v){
        e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
    }
    //dp[i][0]表示i点不被选择时最大值
    //dp[i][1]表示i点被选择时的最大值 
    void tredp(int u){
        dp[u][0]=0,dp[u][1]=r[u];
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            tredp(v);
            dp[u][0]+=max(dp[v][0],dp[v][1]);
            dp[u][1]+=dp[v][0];
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&r[i]);
        for(int a,b,i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            add(b,a);v[a]=1;
        }
        int root; 
        for(int i=1;i<=n;i++) if(!v[i]) root=i;
        tredp(root);
        printf("%d
    ",max(dp[root][0],dp[root][1]));
        return 0;
    } 

    树形DP——倒序队列或栈

    #include<bits/stdc++.h>
    
    #define N 6005
    using namespace std;
    
    int n,r[N],dp[N][2],tot,head[N];
    struct node{
        int to,next;
    }e[N];
    
    bool v[N];
    void add(int u,int v){
        e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
    }
    //dp[i][0]表示i点不被选择时最大值
    //dp[i][1]表示i点被选择时的最大值 
    queue<int>Q;
    stack<int>q;
    bool vis[N];
    void bfs(int root){
        Q.push(root);
        while(!Q.empty()){
            int u=Q.front();Q.pop();q.push(u);
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                if(!vis[v]){
                    vis[v]=1;
                    Q.push(v);
                }
            }
        }
        while(!q.empty()){
            int u=q.top();q.pop();
            for(int i=head[u];i;i=e[i].next){
                int v=e[i].to;
                dp[u][0]+=max(dp[v][0],dp[v][1]);
                dp[u][1]+=dp[v][0];
            }dp[u][1]+=r[u];
        }
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&r[i]);
        for(int a,b,i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            add(b,a);v[a]=1;
        }
        int root; 
        for(int i=1;i<=n;i++) if(!v[i]) root=i;
        bfs(root);
        printf("%d
    ",max(dp[root][0],dp[root][1]));
        return 0;
    } 

    拓扑排序——反向建边

    #include<bits/stdc++.h>
    
    #define N 6005
    using namespace std;
    
    int n,r[N],dp[N][2],tot,head[N],rd[N];
    struct node{
        int to,next;
    }e[N];
    
    void add(int u,int v){
        e[++tot].to=v,e[tot].next=head[u],head[u]=tot;
    }
    //dp[i][0]表示i点不被选择时最大值
    //dp[i][1]表示i点被选择时的最大值 
    bool v[N];
    queue<int>Q;
    void topo(){
        for(int i=1;i<=n;i++) if(!rd[i]) Q.push(i);
        while(!Q.empty()){
            int u=Q.front();Q.pop();dp[u][1]+=r[u];
            for(int i=head[u];i;i=e[i].next){
                int V=e[i].to;
                rd[V]--;
                if(!rd[V]) Q.push(V);
                dp[V][0]+=max(dp[u][1],dp[u][0]);
                dp[V][1]+=dp[u][0];
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d",&r[i]);
        for(int a,b,i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            add(a,b);rd[b]++;v[a]=1;
        }
        int root; 
        for(int i=1;i<=n;i++) if(!v[i]) root=i;
        topo();
        printf("%d
    ",max(dp[root][0],dp[root][1]));
        return 0;
    } 
  • 相关阅读:
    文件读写,尝试filestream和streamreader,streamwriter
    打印控件ScriptX,手动安装ScriptX插件说明 只兼容IE
    JS 循环获取Repeater 中Checkbox1被选中的值
    页面传值出现乱码问题 window.showModalDialog()
    无法打开物理文件 操作系统错误 5:拒绝访问 SQL Sever
    js 获取时间给时间控件赋值
    css 固定在窗口底端
    后台转换JSON格式。ToJson
    JS 匿名函数的使用2
    JS 匿名函数的使用1
  • 原文地址:https://www.cnblogs.com/song-/p/9534704.html
Copyright © 2011-2022 走看看