zoukankan      html  css  js  c++  java
  • 洛谷P1352 没有上司的舞会 [2017年5月计划 清北学堂51精英班Day3]

    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

    A的第一道树形DP的题,想想当年遥不可及的树形DP,现在花了半个小时就写完A掉。。。泪目啊
    用bfs做层序遍历,从tail往前直到1开始遍历。

    状态很简单.
    fi 表示i 人参加了舞会的时候这个子树的欢乐值之和.
    gi 表示i 人没参加舞会的时候这个子树的欢乐值之和.
    转移就更简单了.
    fi = vi +
    Σgjjj is son of i
    gi =
    Σmax(fj; gj)jj is son of i

    ——hja

    就这样。上代码。改BUG的时候偷了一点懒,有点凌乱。


    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #define max(a,b) ((a) > (b) ? (a) : (b))
    #define min(a,b) ((a) > (b) ? (b) : (a))
    #define lowbit(a) ((a) & (-(a)))
    
    int read()
    {
        int x = 0;char ch = getchar();char c = ch;
        while(ch > '9' || ch < '0')c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar();
        if(c == '-')return -x;
        return x;
    }
    
    const int INF = 0x3f3f3f3f;
    const int MAXN = 6000 + 10;
    const int MAXE = MAXN * 2;
    int n,m,cnt,tmp1,tmp2,tmp3,head[MAXN],happy[MAXN],f[MAXN],g[MAXN],queue[MAXN],root;
    bool b[MAXN];//记录哪些点已经在队列中 
    struct Edge
    {
        int u,v,next;
    }edge[MAXE];
    inline void insert(int a,int b)
    {
        edge[++cnt] = Edge{a,b,head[a]};
        head[a] = cnt;
    }
    inline void init()
    {
        n = read();
        for(int i = 1;i <= n;i ++)
        {
            happy[i] = read();
        }
        for(int i = 1;i < n;i ++)
        {
            tmp1 = read();tmp2 = read();
            insert(tmp1, tmp2);
            insert(tmp2, tmp1);
        } 
        root = 1;//拎出一个点当根 
    }
    inline void DP()
    {
        //bfs
        int head = 1,tail = 1;
        queue[tail] = root;
        b[root] = true;
        int a = 1;
        do
        {
            int x = queue[head];
            head ++;
            for(int pos = ::head[x];pos;pos = edge[pos].next)
            {
                int tmp = edge[pos].v;
                if(!b[tmp])
                {
                    queue[++tail] = tmp;
                    b[tmp] = true;
                    a ++;
                }
            }
        }while(a < n );
        for(int j = tail;j >= 1;j --)
        {
            int i = queue[j];
            if(!::head[i])
            {
                g[i] = 0;
                f[i] = happy[i];
            }
            else
            {
                f[i] += happy[i];
                for(int pos = ::head[i];pos;pos = edge[pos].next)
                {
                    int tmp = edge[pos].v;
                    f[i] += g[tmp];
                    g[i] += max(f[tmp], g[tmp]);
                }
            }
        } 
    }
    inline void shuchu()
    {
        printf("%d", max(f[1], g[1]));
    }
    int main()
    {
        init();
        DP();
        shuchu();
            return 0;
    }
  • 相关阅读:
    关于excel导入、导出(POI)
    关于上传图片和显示
    关于sql连接查询(内联、左联、右联、全联)
    关于面试问题
    关于excel导出
    响应式布局和自适应布局的不同
    关于时间范围查询
    HDU 6166 Senior Pan(二进制分组+最短路)
    HUAS 2017暑假第六周比赛-题解
    AtCoder Regular Contest 081
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/6913224.html
Copyright © 2011-2022 走看看