hdu 1520 Anniversary party(树形dp)
题意:
输入一个N,代表树的结点个数,接下来N行代表1到N节点的欢乐值,之后的若干行输入为L和K,表示L的父节点为K,求的是该树最大的欢乐值为多少,需注意的是父子节点不能同时出现。
分析:
用d[i][0] 表示节点i 不出现的最大欢乐值,d[i][0]表示节点i 出现的最大欢乐值。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cmath> 6 #include <algorithm> 7 #include <vector> 8 #define LL __int64 9 const int maxn = 6000+10; 10 using namespace std; 11 int a[maxn], head[maxn], d[maxn][2], ans, vis[maxn], t; 12 struct node 13 { 14 int u, v, to; 15 } e[2*maxn]; 16 void add(int u, int v) 17 { 18 e[t].u = u; 19 e[t].v = v; 20 e[t].to = head[u]; 21 head[u] = t++; 22 } 23 void dfs(int u) 24 { 25 int i, v; 26 27 vis[u] = 1; 28 for(i = head[u]; i != -1; i = e[i].to) 29 { 30 v = e[i].v; 31 if(vis[v]) continue; 32 dfs(v); 33 d[u][1] += d[v][0]; 34 d[u][0] += max(d[v][0], d[v][1]); 35 } 36 } 37 38 int main() 39 { 40 int i, n, l, k; 41 while(~scanf("%d", &n)) 42 { 43 for(i = 1; i <= n; i++) 44 { 45 scanf("%d", &a[i]); 46 d[i][0] = 0; 47 d[i][1] = a[i]; 48 } 49 t = 0; 50 memset(head, -1, sizeof(head)); 51 memset(vis, 0, sizeof(vis)); 52 53 while(~scanf("%d%d", &l, &k)) 54 { 55 if(l==0 && k==0) break; 56 add(k, l); 57 add(l, k); 58 } 59 dfs(1); 60 ans = max(d[1][0], d[1][1]); 61 cout<<ans<<endl; 62 } 63 return 0; 64 }