【问题描述】
有个公司要举行一场晚会。为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司(上司的上司,上司的上司的上司……都可以邀请)。每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大。所有员工的编号为1~N。
【输入格式】
第1行一个整数N(1<=N<=6000)表示公司的人数。
接下来N行每行一个整数。第i行的数表示第i个人的气氛值x(-128<=x<=127)。
接下来每行两个整数L,K。表示K是 L的上司。
输入以0 0结束。
【输出格式】
一个数,最大的气氛值和。
【输入样例】
7
1 1 1 1 1 1 1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
【输出样例】5
【解析】
这道题..
不知道说什么.. 一开始出于习惯瞬间把森林转二叉树打完了..
结果发现根本不用..
只需要用f[i][0]和f[i][1]来存状态..
f[i][0]表示不请i的最大收益
f[i][1]表示请i的最大收益
知道这两个状态就ok了..
然后就TreeDP吧
void Tree_DP ( int x ){ if ( f[x][0] != -1 || f[x][1] != -1 ) return; if ( x < 0 ) return; int i, j, k, f1, f0; f0 = 0; f1 = w[x]; for ( k = first[x]; k; k = a[k].next ){ Tree_DP (a[k].y); f1 += f[a[k].y][0]; f0 += _max ( f[a[k].y][0], f[a[k].y][1] ); } f[x][0] = f0; f[x][1] = f1; }大概就是这样了..
【代码】
#include <cstdio> #include <cstring> #include <cstdlib> using namespace std; int w[6100], n; struct edgenode { int x, y, next; }a[6100]; int first[6100], len; void ins ( int x, int y ){ len ++; a[len].x = x; a[len].y = y; a[len].next = first[x]; first[x] = len; } int f[6100][2]; bool v[6100]; int _max ( int x, int y ){ return x > y ? x : y; } void Tree_DP ( int x ){ if ( f[x][0] != -1 || f[x][1] != -1 ) return; if ( x < 0 ) return; int i, j, k, f1, f0; f0 = 0; f1 = w[x]; for ( k = first[x]; k; k = a[k].next ){ Tree_DP (a[k].y); f1 += f[a[k].y][0]; f0 += _max ( f[a[k].y][0], f[a[k].y][1] ); } f[x][0] = f0; f[x][1] = f1; } int main (){ int i, j, k, x, y; scanf ( "%d", &n ); for ( i = 1; i <= n; i ++ ) scanf ( "%d", &w[i] ); memset ( v, false, sizeof (v) ); while ( scanf ( "%d%d", &x, &y ) && x != 0 || y != 0 ){ ins ( y, x ); v[x] = true; } for ( i = 1; i <= n; i ++ ){ if ( v[i] == false ){ ins ( 0, i ); } } memset ( f, -1, sizeof (f) ); Tree_DP (0); printf ( "%d\n", f[0][0] ); return 0; }