hdu 4616 Game 树形DP


Description

Nowadays, there are more and more challenge game on TV such as ‘Girls, Rush Ahead‘. Now, you participate int a game like this. There are N rooms. The connection of rooms is like a tree. In other words, you can go to any other room by one and only one way. There is a gift prepared for you in Every room, and if you go the room, you can get this gift. However, there is also a trap in some rooms. After you get the gift, you may be trapped. After you go out a room, you can not go back to it any more. You can choose to start at any room ,and when you have no room to go or have been trapped for C times, game overs. Now you would like to know what is the maximum total value of gifts you can get.

Input

The first line contains an integer T, indicating the number of testcases.
For each testcase, the first line contains one integer N(2 <= N <= 50000), the number rooms, and another integer C(1 <= C <= 3), the number of chances to be trapped. Each of the next N lines contains two integers, which are the value of gift in the room and whether have trap in this rooom. Rooms are numbered from 0 to N-1. Each of the next N-1 lines contains two integer A and B(0 <= A,B <= N-1), representing that room A and room B is connected.
All gifts‘ value are bigger than 0.

Output

For each testcase, output the maximum total value of gifts you can get.

Sample Input


2
3 1
23 0
12 0
123 1
0 2
2 1
3 2
23 0
12 0
123 1
0 2
2 1

Sample Output


146
158

 

题目大意:一颗n个点的树,每个点含有一个价值大于0的礼物,且其中有一些点会有陷阱,你有c次机会掉进陷阱,走到一个点就可以获得该点礼物值,走过的点不能再走。

现在起始点任选,让你输出最大获取的礼物值。

学习别人的思路

定义:

down[u][j]表示在从u结点出发往u的子节点方向,前方(包含u)共消耗j次机会所能获得的最大礼物值。

up[u][j]表示从u的子节点方向来,最终到达u结点,共消耗j次机会所能获得的最大礼物值。

状态转移方程:

$$up[u][j+trap[u]] = max(up[u][j+trap[u]],up[v][j]+p[u]);$$

$$down[u][j+trap[u]]=max(down[u][j+trap[u]],down[v][j]+p[u]);$$

其中第二个式子要注意,当$j=0$的时候,down[v][j]的出现显然不符合题意,所以此时不更新。

还有对ans的更新,具体看代码注释。

#include <vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 50005;
int n,c,ans;
vector<int> adj[maxn];
int trap[maxn];
int p[maxn];
int down[maxn][5],up[maxn][5];

void dfs(int u,int fa) {
    up[u][trap[u]] = down[u][trap[u]] = p[u];
    int len = adj[u].size();
    for(int i=0;i<len;i++) {
        int v = adj[u][i];
        if(v==fa) continue;
        dfs(v,u);
        ///更新ans
        for(int j=0;j<=c;j++) //已经耗费j次机会
        {
            for(int k=0;k+j<=c;k++)
            {
                //这里用到的与u有关的up与down,都是限定于之前访问过的u的子树
                //用到含有v的up与down,是当前v的子树
                //这样处理就不会出现“上来”与“下去”是同一条边了,很巧妙
                if(j!=c) //j=c必须停止,因为机会用完了,不能再下去了
                    ans=max(ans,up[u][j]+down[v][k]);
                if(k!=c) //同上
                    ans=max(ans,down[u][j]+up[v][k]);
                if(j+k<c) //只有当两条路机会总和没用完的时候才能把两条路合并
                    ans=max(ans,up[u][j]+up[v][k]);
            }
        }

        ///更新 down[]  up[]
        for(int j=0;j<=c;j++)
        {
            up[u][j+trap[u]] = max(up[u][j+trap[u]],up[v][j]+p[u]);
            if(j!=0)
            {
                down[u][j+trap[u]]=max(down[u][j+trap[u]],down[v][j]+p[u]);
            }
        }
    }

}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&c);
        for(int i=0;i<n;i++) {
            scanf("%d%d",&p[i],&trap[i]);
        }
        for (int i=1; i<n; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            adj[x].push_back(y);
            adj[y].push_back(x);
        }
        ans = 0;
        memset(down,0,sizeof(down));
        memset(up,0,sizeof(up));
        dfs(0,-1);
        printf("%d\n",ans);
        for(int i=0;i<=n;i++) adj[i].clear();
    }
    return 0;
}
时间: 2024-10-07 01:51:47

hdu 4616 Game 树形DP的相关文章

hdu 1011(树形dp)

Mark.看着吴神博客写的,还未完全懂. 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <set> 8 #include <map> 9 #include <string>

HDU 2196Computer(树形DP)

给你一颗边带权值的树,求树上的每一点距离其最远的一个点的距离 比较典型的题了,主要方法是进行两次DFS,第一次DFS求出每一个点距离它的子树的最远距离和次远距离,然后第二次DFS从父节点传过来另一侧的树上的距离它的最远距离进行一次比较便可得出任意点的最远距离了 之所以需要记录最远和次远是为了辨别父节点的最远距离是否是根据自己得来,如果是的话应该选择父节点的次远距离,保证结果的准确性 1 //#pragma comment(linker,"/STACK:102400000,102400000&qu

HDU 2196 Computer 树形DP经典题

链接:http://acm.hdu.edu.cn/showproblem.php? pid=2196 题意:每一个电脑都用线连接到了还有一台电脑,连接用的线有一定的长度,最后把全部电脑连成了一棵树,问每台电脑和其它电脑的最远距离是多少. 思路:这是一道树形DP的经典题目.须要两次DFS,第一次DFS找到树上全部的节点在不同子树中的最远距离和次远的距离(在递归中进行动态规划就可以),第二次DFS从根向下更新出终于答案.对于每次更新到的节点u,他的最远距离可能是来自u的子树,或者是u的父亲节点的最远

HDU 4714 Tree2cycle (树形DP)

题意:给定一棵树,断开一条边或者接上一条边都要花费 1,问你花费最少把这棵树就成一个环. 析:树形DP,想一想,要想把一棵树变成一个环,那么就要把一些枝枝叶叶都换掉,对于一个分叉是大于等于2的我们一定要把它从父结点上剪下来是最优的, 因为如果这样剪下来再粘上花费是2(先不管另一端),如果分别剪下来再拼起来,肯定是多花了,因为多了拼起来这一步,知道这,就好做了.先到叶子结点, 然后再回来计算到底要花多少. 代码如下: #pragma comment(linker, "/STACK:10240000

HDU 3899 简单树形DP

题意:一棵树,给出每个点的权值和每条边的长度, 点j到点i的代价为点j的权值乘以连接i和j的边的长度.求点x使得所有点到点x的代价最小,输出 虽然还是不太懂树形DP是什么意思,先把代码贴出来把. 这道题目的做法是:先进行一次DFS,以每个节点为根,求出它下面节点到它的数量和. 再进行一次DFS,以每个节点为根,求出它下面节点到它的花费总和. source code: #pragma comment(linker, "/STACK:16777216") //for c++ Compile

HDU 4313 Matrix 树形dp

题意: 给定n个点的树,m个黑点 以下n-1行给出边和删除这条边的费用 以下m个黑点的点标[0,n-1] 删除一些边使得随意2个黑点都不连通. 问删除的最小花费. 思路: 树形dp 每一个点有2个状态,成为黑点或白点. 若本身这个点就是黑点那么仅仅有黑点一种状态. 否则能够觉得是子树中某个黑点转移上来. 所以dp[i][0]是i点为黑点的状态. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <st

HDU 2196 Computer 树形DP 经典题

给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权,放在数组cost中 令tree(i)表示以节点i为根的子树 对于节点i,离该节点最远的点要不就是在tree(i)中,要不就是在father(i)上面 令: dp[i][1] : 在子树tree(i)中,离i最远的距离 dp[i][2] : 在子树tree(i)中,离i第二远的距离 (递推的时候需要)

hdu 5148 Cities(树形dp)

题目链接:hdu 5148 Cities dp[i][j]表示以i为根节点,选j个最优值,每条边被选中的时候就计算出被经过的次数,并乘上权值. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> pii; typedef long long ll; const

HDU 2196-Computer(树形dp)

题意: 给出电脑网络连接树,求每个节点的为起点的最长距离 分析: 这道题开始状态想不出来,放了一段时间,后来注意到例题上有这道题,每个节点的最长距离可由父节点的最长距离,次长距离,和子节点的最长距离(三者取最大)决定.先用一个dfs求出各节点由各子树确定的最长距离,次长距离,再用一个dfs由父节点推各子节点的最长距离. #include <map> #include <set> #include <list> #include <cmath> #includ