洛谷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;
}

 

posted @ 2017-05-27 15:51  嘒彼小星  阅读(204)  评论(0编辑  收藏  举报