题目链接:

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

题目大意:

给一棵树,每个节点有一个礼物值及是否有trick,每来到一个节点必须拿礼物,如果该节点有trick则浪费一个抗trick机会,如果一开始有C次抗trick的机会,问最多可以拿多少值的礼物,机会用完后就结束了。访问了的节点不能再次访问。

解题思路:

树形dp啊。

树形dp很不熟悉阿阿阿阿阿阿阿阿。。。。

dp[i][j][0]表示从节点i开始,有j次机会,在子树中最大的能拿到礼物的值。

dp[i][j][1]表示从节点i开始,有j次机会,在子树中次大的能拿到礼物的值。

by[i][j]表示i节点,有j次机会时,得到最大值的那个直接儿子标号。

先以任意一点为根,dfs一遍。求出从每个节点的开始的在子树中的最大值和次大值。

再以同一点为根,dfs一遍,参数维护一个以父亲为开始节点且不经过该节点的最大值。求出该节点出发的在整棵树中的最大值。

PS:

注意此题麻烦的地方是,当机会恰好用完时,游戏结束,不能累加后面的0机会值。

所以要分该节点是否有trick来判断,如果有trick的话,只有j>=2时有从后面更新。

PS2:要多做树形dp啊。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std; //freopen("data.in","r",stdin);
//freopen("data.out","w",stdout); #define Maxn 55000
ll dp[Maxn][5][2]; //dp[i][j][0]表示从i节点开始有j个机会,在子树中能达到的最大值
int tra[Maxn],val[Maxn],cnt,n,c;
int by[Maxn][5];
ll ans; struct Edge //邻接表
{
int v;
struct Edge * next;
}edge[Maxn<<1],*head[Maxn<<1]; void add(int a,int b)
{
++cnt;
edge[cnt].v=b,edge[cnt].next=head[a];
head[a]=&edge[cnt];
}
ll Max(ll a,ll b)
{
return a>b?a:b;
}
void dfs1(int pre,int cur)
{
struct Edge * p=head[cur];
bool flag=true;
while(p)
{
if(p->v!=pre)
{
flag=false;
dfs1(cur,p->v); //先计算出子树情况
if(tra[cur]) //该节点有trick
{
dp[cur][1][0]=val[cur];
for(int i=2;i<=c;i++) //必须大于等于2的情况才可能从后面更新
{
if(dp[p->v][i-1][0]+val[cur]>=dp[cur][i][0])
{
dp[cur][i][1]=dp[cur][i][0];//更新次大
dp[cur][i][0]=dp[p->v][i-1][0]+val[cur];
by[cur][i]=p->v;
}
else if(dp[p->v][i-1][0]+val[cur]>dp[cur][i][1])
{ //更新次大
dp[cur][i][1]=dp[p->v][i-1][0]+val[cur];
}
}
}
else
{ //如果没有trick,则可以到达其他点任何点
for(int i=0;i<=c;i++)
{
if(dp[p->v][i][0]+val[cur]>=dp[cur][i][0])
{
dp[cur][i][1]=dp[cur][i][0];
dp[cur][i][0]=dp[p->v][i][0]+val[cur];
by[cur][i]=p->v;
}
else if(dp[p->v][i][0]+val[cur]>dp[cur][i][1])
{
dp[cur][i][1]=dp[p->v][i][0]+val[cur];
}
}
}
}
p=p->next;
}
if(flag) //叶子节点单独处理
{
for(int i=tra[cur];i<=c;i++)
dp[cur][i][0]=val[cur];
}
}
void dfs2(int pre,int cur,ll *aa)
{
ll MM=0;
if(tra[cur])
{
MM=dp[cur][c][0];//从子树中找
if(c>=2)
MM=Max(MM,aa[c-1]+val[cur]); //从父亲找
}
else
MM=Max(dp[cur][c][0],aa[c]+val[cur]);
if(MM>ans)
ans=MM;
/* printf("cur:%d ans:%I64d \n",cur,MM);
for(int i=0;i<=c;i++)
printf("aa[%d]:%I64d ",i,aa[i]);
putchar('\n');
system("pause");*/
struct Edge * p=head[cur];
while(p)
{
if(p->v!=pre)
{
ll tt[5]={0}; //tt[i]表示父亲有i次机会且不通过该儿子时能达到的最大值
if(tra[cur])
{
tt[1]=dp[cur][1][0]; //注意更新
for(int i=2;i<=c;i++)
{
if(p->v!=by[cur][i]) //最大值是该儿子,用次大的来更新
tt[i]=Max(aa[i-1]+val[cur],dp[cur][i][0]);
else
tt[i]=Max(aa[i-1]+val[cur],dp[cur][i][1]);
}
}
else
{
for(int i=0;i<=c;i++)
{
if(p->v!=by[cur][i])
tt[i]=max(aa[i]+val[cur],dp[cur][i][0]);
else
tt[i]=max(aa[i]+val[cur],dp[cur][i][1]);
}
}
/* for(int i=0;i<=c;i++)
printf("i:%d %d\n",i,tt[i]);*/
dfs2(cur,p->v,tt);
}
p=p->next;
} } int main()
{
int t,a,b; //freopen("1006.in","r",stdin);
//freopen("1006ans.out","w",stdout);
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&c);
memset(by,-1,sizeof(by));
memset(head,NULL,sizeof(head));
for(int i=0;i<n;i++)
scanf("%d%d",&val[i],&tra[i]);
cnt=0;
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
memset(dp,0,sizeof(dp));
ans=0;
dfs1(-1,0);
ll tt[5]={0};
dfs2(-1,0,tt);
printf("%I64d\n",ans);
}
return 0;
}

树形dp hdu-4616-Game的更多相关文章

  1. fwt优化+树形DP HDU 5909

    //fwt优化+树形DP HDU 5909 //见官方题解 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ #include <bits/ ...

  2. HDU - 1054 Strategic Game(二分图最小点覆盖/树形dp)

    d.一颗树,选最少的点覆盖所有边 s. 1.可以转成二分图的最小点覆盖来做.不过转换后要把匹配数除以2,这个待细看. 2.也可以用树形dp c.匈牙利算法(邻接表,用vector实现): /* 用ST ...

  3. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  4. HDU 4616 Game (搜索)、(树形dp)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4616 这道题目数据可能比较弱,搜索都可以AC,但是不敢写,哎…… 搜索AC代码: #include & ...

  5. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  6. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. POJ 2342 &&HDU 1520 Anniversary party 树形DP 水题

    一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点) ...

  8. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  9. hdu 4003 Find Metal Mineral 树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal miner ...

  10. 树形DP+树状数组 HDU 5877 Weak Pair

    //树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...

随机推荐

  1. 【UOJ 34】 多项式乘法 (FFT)

    [题意] 给你两个多项式,请输出乘起来后的多项式. 先打一个递归版本的模板... #include<cstdio> #include<iostream> #include< ...

  2. 最大流KK算法

    最大流KK算法 #include<iostream> #include<stdio.h> #include<string.h> #include<math.h ...

  3. GeoIP的使用

    GeoIP介绍: 什么是GepIP ? 所谓GeoIP,就是通过来访者的IP, 定位他的经纬度,国家/地区,省市,甚至街道等位置信息.这里面的技术不算难题,关键在于有个精准 的数据库.有了准确的数据源 ...

  4. FIS构建工具学习(一)

    一.FIS是什么 在做项目的时候,用到部门内部前端人员开发的fiskit构建工具,经过这次项目基本把它的配置弄清楚了,fiskit构建工具是基于FIS的,所以自己也准备学习FIS,以便更好的理解. 后 ...

  5. Ural 1519 Formula 1 插头DP

    这是一道经典的插头DP单回路模板题. 用最小表示法来记录连通性,由于二进制的速度,考虑使用8进制. 1.当同时存在左.上插头的时候,需要判断两插头所在连通块是否相同,若相同,只能在最后一个非障碍点相连 ...

  6. Codeforces Beta Round #5 D. Follow Traffic Rules 物理

    D. Follow Traffic Rules 题目连接: http://www.codeforces.com/contest/5/problem/D Description Everybody kn ...

  7. java内存分配 常量池详解

    http://www.cnblogs.com/qinqinmeiren/archive/2011/07/19/2151683.html

  8. 使用hadoop实现关联商品统计

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/40184581 近期几天一直在看hadoop相关的书籍,眼下略微有点感觉,自己就仿 ...

  9. 记一次压力测试和对nginx/tomcat配置的调整

    原文地址:还没找到 是一个web系统,前端使用nginx做为反向代理,处理https,并将请求转发给后端的tomcat服务. 压力测试工具选择了jmeter. 首先简单介绍一下jmeter. 它是ap ...

  10. HTML+CSS网站开发兵书

    <HTML+CSS网站开发兵书> 基本信息 作者: 高洪涛 丛书名: 程序员藏经阁 出版社:电子工业出版社 ISBN:9787121212369 上架时间:2013-8-26 出版日期:2 ...