HDU 4616 Game(经典树形dp+最大权值和链)

http://acm.hdu.edu.cn/showproblem.php?pid=4616

题意:
给出一棵树,每个顶点有权值,还有存在陷阱,现在从任意一个顶点出发,并且每个顶点只能经过一次,如果经过了c个陷阱就不能再走了,计算最大能获得的权值和。

思路:
有点像树链剖分,对于一个以u为根的子树,因为每个顶点只能经过一次,那我们只能选择它的一个子树往下走。就像是把这棵树分成许多链,最后再连接起来。

这道题目麻烦的地方是陷阱的处理,用d【u】【j】【0/1】表示以u为根的某一子节点经过j个陷阱后到达u的最大权值和,0/1表示起点是否有陷阱。

假设当前到达u时经过了k个陷阱,分下面几种情况进行讨论:

①如果k==c,那么起点和终点至少有一个是陷阱(可能有些人会认为终点一定会是陷阱,这样是没错的,因为起点和终点时相对的,你也可以把起点看做终点)。

②如果k<c,那么起点和终点是否是陷阱是任意的,可以有也可以没有。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<sstream>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<cmath>
10 #include<map>
11 #include<set>
12 using namespace std;
13 typedef long long ll;
14 typedef pair<int,int> pll;
15 const int INF = 0x3f3f3f3f;
16 const int maxn = 50000 + 5;
17
18 int n,c;
19 int ans;
20 int val[maxn], trap[maxn];
21 int d[maxn][5][2];
22 vector<int> G[maxn];
23
24 void dfs(int u, int fa)
25 {
26     d[u][trap[u]][trap[u]]=val[u];
27
28     for(int i=0;i<G[u].size();i++)
29     {
30         int v=G[u][i];
31         if(v==fa)  continue;
32         dfs(v,u);
33
34         //计算以u为根的子树所能获得的最大值,也就是将子树的链进行连接
35         for(int j=0;j<=c;j++)
36         {
37             for(int k=0;j+k<=c;k++)
38             {
39                 if(j!=c)   ans=max(ans,d[u][j][0]+d[v][k][1]);
40                 if(k!=c)   ans=max(ans,d[u][j][1]+d[v][k][0]);
41                 if(j+k<c)  ans=max(ans,d[u][j][0]+d[v][k][0]);  //起点和终点都可以为非陷阱
42                 if(k+j<=c) ans=max(ans,d[u][j][1]+d[v][k][1]);  //起点和终点都可以为陷阱
43             }
44         }
45
46
47         for(int j=0;j+trap[u]<=c;j++)  //更新以u的根的子树中权值最大的链
48         {
49             d[u][j+trap[u]][0]=max(d[u][j+trap[u]][0],d[v][j][0]+val[u]);
50             //这儿要注意一下,如果j=0时,要么就不能从有陷阱的起点出发
51             if(j!=0) d[u][j+trap[u]][1]=max(d[u][j+trap[u]][1],d[v][j][1]+val[u]);
52         }
53     }
54 }
55
56 int main()
57 {
58     //freopen("in.txt","r",stdin);
59     int T;
60     scanf("%d",&T);
61     while(T--)
62     {
63         scanf("%d%d",&n,&c);
64         for(int i=0;i<n;i++)  G[i].clear();
65
66         for(int i=0;i<n;i++)
67             scanf("%d%d",&val[i],&trap[i]);
68
69         for(int i=1;i<n;i++)
70         {
71             int u,v;
72             scanf("%d%d",&u,&v);
73             G[u].push_back(v);
74             G[v].push_back(u);
75         }
76
77         ans=0;
78         memset(d,0,sizeof(d));
79         dfs(0,-1);
80         printf("%d\n",ans);
81     }
82     return 0;
83 }
时间: 2024-10-19 01:59:28

HDU 4616 Game(经典树形dp+最大权值和链)的相关文章

HDU 2196 Computer 经典树形DP

一开始看错题了,后来发现原来是在一颗带权的树上面求出距离每一个点的最长距离,做两次dfs就好,具体的看注释? #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #incl

HDU 3534 Tree (经典树形dp)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3534 题意: 给你一棵树,问你有多少对点的距离等于树的直径. 思路: dp[i][0]表示在i的子树中 离i最远的距离,dp[i][1]是次远距离.   cnt[i][0]则是最远的点的数量,cnt[i][1]表示次远的数量. up[i]表示以i向上 离i最远的距离.   up_cnt[i]表示向上最远的数量. 写的有点麻烦,调试了2小时... 1 //#pragma comment(linker,

poj 1947 经典树形dp

经典树形dp:问在一棵树上最少删除多少条边可以分离出一个节点数为p的子树. 定义状态: dp[i][j]表示从i为根的子树上分离出一个节点数为j的子树的代价(最少需要删除的边数). 考虑i节点的每个儿子ii,ii可以选或者不选(切断),然后就转化成了背包问题. dp[u][j] = min( dp[u][j], dp[u][j - k] + dp[v][k] ); 1 #include <iostream> 2 #include <cstring> 3 #include <c

HDU 1011 Starship Troopers(树形DP)

Starship Troopers Time Limit : 10000/5000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submission(s) : 62   Accepted Submission(s) : 12 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description You, the leader of

hdu 1520Anniversary party(简单树形dp)

Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4310    Accepted Submission(s): 1976 Problem Description There is going to be a party to celebrate the 80-th Anniversary of the

hdu 4044 GeoDefense (树形dp+01背包)

GeoDefense Time Limit: 12000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 663    Accepted Submission(s): 267 Problem Description Tower defense is a kind of real-time strategy computer games. The goal of towe

hdu 5452 Minimum Cut 树形dp

Minimum Cut Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5452 Description Given a simple unweighted graph G (an undirected graph containing no loops nor multiple edges) with n nodes and m edges. Let T be a spa

HDU 2376 Average distance (树形dp)

Average distance Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 588    Accepted Submission(s): 213 Special Judge Problem Description Given a tree, calculate the average distance between two ve

POJ 2342 &amp;&amp;HDU 1520 Anniversary party 树形DP 水题

一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点)都不能被邀请 2.每一个员工都有一个兴奋值,在满足1的条件下,要使得邀请来的员工的兴奋值最高 输出最高的兴奋值. 简单的树形DP dp[i][1]:表示以i为根的子树,邀请节点i的最大兴奋值 dp[i][0]:表示以i为根的子树,不邀请节点i的最大兴奋值 先根据入度找出整棵树的根节点, 然后一次DF