ural 1039 树dp

http://acm.timus.ru/problem.aspx?space=1&num=1039

1039. Anniversary Party

Time limit: 0.5 second
Memory limit: 8 MB

Background

The
president of the Ural State University is going to make an 80‘th
Anniversary party. The university has a hierarchical structure of
employees; that is, the supervisor relation forms a tree rooted at the
president. Employees are numbered by integer numbers in a range from 1
to N, The personnel office has ranked each employee with a
conviviality rating. In order to make the party fun for all attendees,
the president does not want both an employee and his or her immediate
supervisor to attend.

Problem

Your task is to make up a guest list with the maximal conviviality rating of the guests.

Input

The first line of the input contains a number N. 1 ≤ N ≤ 6000.
Each of the subsequent N lines contains the conviviality rating of the corresponding employee.
Conviviality rating is an integer number in a range from –128 to 127. After that the supervisor relation tree goes.
Each line of the tree specification has the form

<L> <K>

which means that the K-th employee is an immediate supervisor of L-th employee. Input is ended with the line

0 0

Output

The output should contain the maximal total rating of the guests.

Sample

input output
7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0
5

树上的树dp例题,f[i][0]表示以i为根不包含i可获得的最大价值,f[i][1]表示以i为根包含i在内可获得的最大价值。有f[i][0]+=MAX{f[son[i]][0],f[son[i]][1] } ,f[i][1]+=f[son[i]][0];

因为一旦包含i了显然不能包含i的儿子,所以不能加上f[son[i]][1],反之取二者中较大的就好了。

因为如何保存他们之间的关系想了半天,想用vector来着,看书上写的很简便,利用数组做邻接表处理。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 #define LL long long
 7 #define inf 0x3f3f3f3f
 8 int c[6005],fa[6005],son[6005],bro[6005];
 9 int dp[6005][2];
10 void solve(int id)
11 {
12     dp[id][0]=0;
13     dp[id][1]=c[id];
14     for(int i=son[id];i!=-1;i=bro[i])
15     {
16         solve(i);
17         dp[id][0]+=max(dp[i][0],dp[i][1]);
18         dp[id][1]+=dp[i][0];
19     }
20 }
21 int main()
22 {
23     int N,i,j,k;
24     while(cin>>N){
25         int a,b,root;
26         memset(fa,-1,sizeof(fa));
27         memset(son,-1,sizeof(son));
28         memset(bro,-1,sizeof(bro));
29         for(i=1;i<=N;++i) scanf("%d",c+i);
30         while(scanf("%d%d",&a,&b)&&(a||b)){
31             fa[a]=b;
32             bro[a]=son[b];
33             son[b]=a;
34         }
35         for(i=1;i<=N;++i){
36             dp[i][0]=0,dp[i][1]=c[i];
37             if(fa[i]==-1) root=i;
38         }
39         solve(root);
40         printf("%d\n",max(dp[root][0],dp[root][1]));
41     }
42     return 0;
43 }
时间: 2024-10-08 01:11:02

ural 1039 树dp的相关文章

树形DP URAL 1039 Anniversary Party

题目传送门 1 /* 2 题意:上司在,员工不在,反之不一定.每一个人有一个权值,问权值和最大多少. 3 树形DP:把上司和员工的关系看成根节点和子节点的关系,两者有状态转移方程: 4 dp[rt][0] += max (dp[son][1], dp[son][0]); //上司不去 5 dp[rt][1] += dp[son][0]; //上司去,员工都不去 6 */ 7 #include <cstdio> 8 #include <cstring> 9 #include <

Ural 1018 binary apple tree(显性树的树dp)

题意:一棵含n个节点的树,保留m条边,使含m条边的子树的边权和最大: 思路:树dp.求含m+1个节点边权和最大的子树.对每个分支节点有三种操作:剪去左子树:剪去右子树:将其节点数合理分配给左右子树: 记以x为根,含k个节点的子树的最大边权和为g[x][k]. 若x为叶节点,则g[x][k]为x通往父节点的边权:若非叶节点,枚举k-1个节点分配在左右子树的所有可能方案,找到最佳方案: #include<cstdio> #include<cstring> #include<alg

2010辽宁省赛 NBUT 1222 English Game【字典树+DP】

[1222] English Game 时间限制: 1000 ms 内存限制: 131072 K 链接:Click Here! 问题描述 This English game is a simple English words connection game. The rules are as follows: there are N English words in a dictionary, and every word has its own weight v. There is a wei

uva 12452 Plants vs. Zombies HD SP (树DP)

Problem I: Plants vs. Zombies HD Super Pro Plants versus Zombies HD Super Pro is a game played not a grid, but on a connected graph G with no cycles (i.e., a tree). Zombies live on edges of the tree and chew through edges so that tree falls apart! Pl

hdu 3016 Man Down (线段树 + dp)

题目大意: 是男人就下一般层...没什么可以多说的吧. 注意只能垂直下落. 思路分析: 后面求最大值的过程很容易想到是一个dp的过程 . 因为每一个plane 都只能从左边 从右边下两种状态. 然后我们所需要处理的问题就是 ,你如何能快速知道往左边下到哪里,往右边下到哪里. 这就是线段树的预处理. 讲线段按照高度排序. 然后按照高度从小到大加入到树中. 然后去寻找左端点 和 右端点最近覆盖的线段的编号. #include <cstdio> #include <iostream> #

ZOJ3632 线段树+DP

买西瓜吃,每个西瓜有两个参数,一个是p代表价格,一个是t代表能吃几天,要求n天每天都能吃西瓜,而且如果你今天买了,以前买的还没吃完 那么都得扔了,求最小花费,还真想不到用线段树+DP,最后看了一下别人的标题,想了一下,DP方程挺好推的,线段树也只是单点查询, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #inclu

hdu 4863 Centroid of a Tree 树dp

代码来自baka.. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<set> #include<cmath> #include<vecto

[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 220000 #define inf 0x3ffffffffffffffLL typedef long long ll; int v[N],e[N],ne[N],nn,w[N]; void add(int x,int y,int z){ ne[++nn

【HDU 5647】DZY Loves Connecting(树DP)

pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 332    Accepted Submission(s): 112 Problem Description DZY has an unroote