↓ 跳过正文
  1. Posts/

hdu 1520 Anniversary party (树形dp模板题)

·610 字·2 分钟

题目链接 题意:一个舞会,每个人有一个val,给出n个人之间的领导和被领导关系,一个人不愿意与他的领导同时参加,问一种安排方案,使得参加的人的val和最大,问这个最大的和是多少。

思路:树形dp模板题。

dp1[v]表示包含v节点的子树的最大值。

dp2[v]表示,不包含v节点的子树的最大值。

下面讲得很清楚。。

Now, similar to array problem, we have to make a decision about including node V in our subset or not. If we include node V, we can’t include any of its children(say _v_1, _v_2, …, v__n), but we can include any grand child of V. If we don’t include V, we can include any child of V.

So, we can write a recursion by defining maximum of two cases.

两种情况取最大值
.

As we see in most DP problems, multiple formulations can give us optimal answer. Here, from an implementation point of view, we can define an easier solution using DP. We define two DPs,

dp1(V)
and
dp2(V)
, denoting maximum coins possible by choosing nodes from subtree of node V and if we include node V in our answer or not, respectively. Our final answer is maximum of two case i.e.
最终答案的 max 表达式
.

And defining recursion is even easier in this case.

包含 V 时的递推式
(since we cannot include any of the children) and
不包含 V 时的递推式
(since we can include children now, but we can also choose not include them in subset, hence max of both cases).

代码实现
 1/* ***********************************************
 2Author :111qqz
 3Created Time :2016年11月30日 星期三 20时37分22秒
 4File Name :code/hdu/1520.cpp
 5************************************************ */
 6#include <cstdio>
 7#include <cstring>
 8#include <iostream>
 9#include <algorithm>
10#include <vector>
11#include <queue>
12#include <set>
13#include <map>
14#include <string>
15#include <cmath>
16#include <cstdlib>
17#include <ctime>
18#define fst first
19#define sec second
20#define lson l,m,rt<<1
21#define rson m+1,r,rt<<1|1
22#define ms(a,x) memset(a,x,sizeof(a))
23typedef long long LL;
24#define pi pair < int ,int >
25#define MP make_pair
26using namespace std;
27const double eps = 1E-8;
28const int dx4[4]={1,0,0,-1};
29const int dy4[4]={0,-1,1,0};
30const int inf = 0x3f3f3f3f;
31const int N=6E3+7;
32int a[N];
33int n;
34int dp1[N],dp2[N];
35vector <int>edge[N];
36int in[N];
37int root;
38void dfs(int u,int pre)
39{
40    int sum1=0,sum2=0;
41    for ( auto v: edge[u])
42    {
43	if (v==pre) continue;
44	dfs(v,u);
45	sum1+=dp2[v];
46	sum2+=max(dp1[v],dp2[v]);
47    }
48    dp1[u] = a[u] + sum1;
49    dp2[u] = sum2;
50}
51int main()
52{
53	#ifndef  ONLINE_JUDGE
54	freopen("code/in.txt","r",stdin);
55  #endif
56	while (~scanf("%d",&n))
57	{
58	    ms(in,0);
59	    ms(dp1,0);
60	    ms(dp2,0);
61	    for ( int i = 1 ;i <= n ; i++) edge[i].clear();
62	    for ( int i = 1; i <= n ; i++) scanf("%d",&a[i]);
63	    int u,v;
64	    while (~scanf("%d%d",&u,&v))
65	    {
66		if (u==0&&v==0) break;
67		edge[u].push_back(v);
68		edge[v].push_back(u);
69		in[u]++;
70	    }
71	    for ( int i = 1 ; i <= n ; i++)
72		if (in[i]==0)
73		{
74		    root = i;
75		    break;
76		}
77	    dfs(root,-1);
78	    int ans = max(dp1[root],dp2[root]);
79	    printf("%d\n",ans);
80	}
81  #ifndef ONLINE_JUDGE
82  fclose(stdin);
83  #endif
84    return 0;
85}

相关文章

hdu 2196 Computer (树的直径||树形dp)

·1552 字·4 分钟
hdu 2196 题意:给出一棵树,求距离每个点的最远距离是多少。 思路:最远距离什么的,能想到树的直径,但是有什么关系呢?我们在求树的直径的时候,直径的两个端点是可以知道的。如果再从两个端点分别做两次 bfs,每个点取两个距离的较大值就是答案。。?

poj 2342 Anniversary party (基础树形dp)

·634 字·2 分钟
题目链接 题意:n个人的上下级关系形成一棵树..每一个人有一个val(可正可负),要选若干个人参加一个party,要求是一个人和他的直接上级不能同时在场。问参加party的人最大的val之和。

(转)树形dp题目集

·2713 字·6 分钟
树,一种十分优美的数据结构,因为它本身就具有的递归性,所以它和子树间能相互传递很多信息,还因为它作为被限制的图在上面可进行的操作更多,所以各种用于不同地方的树都出现了,二叉树、三叉树、静态搜索树、AVL树,线段树、SPLAY树,后缀树等等.. 枚举那么多种数据结构只是想说树方面的内容相当多,本专辑只针对在树上的动态规划,即树形DP.做树形DP一般步骤是先将树转换为有根树,然后在树上进行深搜操作,从子节点或子树中返回信息层层往上更新至根节点。这里面的关键就是返回的信息部分,这个也没一般性的东西可讲,因为每道题目要求做的事都不尽相同。