洛谷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:
用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的时候偷了一点懒,有点凌乱。
5A的第一道树形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; }