又学到东西了,树形DP。
参考了网上的代码,使用的是孩子,兄弟,父节点的模式建树。
node[idx].present表示的是第idx个节点参加的时候的最优,node[idx].not_present表示的是第idx个节点不参加的时候的最优。
/******************************************************************************* # Author : Neo Fung # Email : [email protected] # Last modified: 2012-04-26 19:22 # Filename: POJ2342 HDU1520 Anniversary party.cpp # Description : ******************************************************************************/ #ifdef _MSC_VER #define DEBUG #define _CRT_SECURE_NO_DEPRECATE #endif #include <fstream> #include <stdio.h> #include <iostream> #include <string.h> #include <string> #include <limits.h> #include <algorithm> #include <math.h> #include <numeric> #include <functional> #include <ctype.h> #define MAX 100010 using namespace std; struct NODE { int child,father,brother,present,not_present; int max() { return present>not_present?present:not_present; } void init() { child=father=brother=not_present=0; } }node[MAX]; void dfs(const int &idx) { int child=node[idx].child; while(child) { dfs(child); node[idx].present+=node[child].not_present;//第idx个参加,则孩子节点不能参加 node[idx].not_present+=node[child].max(); //第idx个不参加,则孩子节点可参加可不参加 child=node[child].brother; } } int main(void) { #ifdef DEBUG freopen("../stdin.txt","r",stdin); freopen("../stdout.txt","w",stdout); #endif int n; while(~scanf("%d",&n) && n) { for(int i=1;i<=n;++i) { scanf("%d",&node[i].present); node[i].init(); } int k,l; while(scanf("%d%d",&l,&k) && k+l) { node[l].father=k; node[l].brother=node[k].child; node[k].child=l; } for(int i=1;i<=n;++i) if(!node[i].father) { dfs(i); printf("%d\n",node[i].max()); break; } } return 0; }