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 }

 

posted @ 2016-08-28 21:55  Recoder  阅读(205)  评论(0编辑  收藏  举报