POJ 2342 Anniversary party (树dp)
题目链接:http://poj.org/problem?id=2342
有n个人,每个人有活跃值。下面n-1行u和v表示u的上司是v,有直接上司和下属的关系不能同时参加party,问你party最大的活跃值是多少。
也就是说一棵树中,选择的点不能是相邻的点,且要使活跃值最大。
简单的树形dp,任意选一个点开始遍历,从叶子节点开始回溯。
dp[i][0]表示不选i节点最大的活跃度,则dp[i][1]表示选i节点最大的活跃度。
i与j相连,dp[i][0] += max(dp[j][0], dp[j][1]); dp[i][1] += dp[j][0];
1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <ctime> 10 #include <list> 11 #include <set> 12 #include <map> 13 using namespace std; 14 typedef long long LL; 15 typedef pair <int, int> P; 16 const int N = 1e4 + 5; 17 struct Edge { 18 int next, to; 19 }edge[N << 1]; 20 int dp[N][2]; 21 int a[N], cnt, head[N]; 22 23 inline void add(int u, int v) { 24 edge[cnt].to = v; 25 edge[cnt].next = head[u]; 26 head[u] = cnt++; 27 } 28 29 void dfs(int u, int p) { 30 dp[u][0] = 0; 31 dp[u][1] = a[u]; 32 for(int i = head[u]; ~i; i = edge[i].next) { 33 int v = edge[i].to; 34 if(v == p) 35 continue; 36 dfs(v, u); 37 dp[u][0] += max(dp[v][0], dp[v][1]); 38 dp[u][1] += dp[v][0]; 39 } 40 } 41 42 int main() 43 { 44 int n, u, v; 45 while(~scanf("%d", &n)) { 46 for(int i = 1; i <= n; ++i) 47 scanf("%d", a + i); 48 memset(head, -1, sizeof(head)); 49 cnt = 0; 50 for(int i = 1; i < n; ++i) { 51 scanf("%d %d", &u, &v); 52 add(u, v); 53 add(v, u); 54 } 55 scanf("%d %d", &u, &v); //0 0 56 dfs(1, -1); 57 printf("%d\n", max(dp[1][0], dp[1][1])); 58 } 59 return 0; 60 }