树形dp hdu-4616-Game
题目链接:
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的更多相关文章
- fwt优化+树形DP HDU 5909
//fwt优化+树形DP HDU 5909 //见官方题解 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ #include <bits/ ...
- HDU - 1054 Strategic Game(二分图最小点覆盖/树形dp)
d.一颗树,选最少的点覆盖所有边 s. 1.可以转成二分图的最小点覆盖来做.不过转换后要把匹配数除以2,这个待细看. 2.也可以用树形dp c.匈牙利算法(邻接表,用vector实现): /* 用ST ...
- 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分
树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...
- HDU 4616 Game (搜索)、(树形dp)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4616 这道题目数据可能比较弱,搜索都可以AC,但是不敢写,哎…… 搜索AC代码: #include & ...
- HDU 1520 树形dp裸题
1.HDU 1520 Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...
- HDU 1561 树形DP入门
The more, The Better Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- POJ 2342 &&HDU 1520 Anniversary party 树形DP 水题
一个公司的职员是分级制度的,所有员工刚好是一个树形结构,现在公司要举办一个聚会,邀请部分职员来参加. 要求: 1.为了聚会有趣,若邀请了一个职员,则该职员的直接上级(即父节点)和直接下级(即儿子节点) ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- hdu 4003 Find Metal Mineral 树形DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal miner ...
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
随机推荐
- Can you find it? HDU - 2141 (二分查找)
Give you three sequences of numbers A, B, C, then we give you a number X. Now you need to calculate ...
- Python中的模块(1)
Python中的模块 有过C语言编程经验的朋友都知道在C语言中如果要引用sqrt这个函数,必须用语句"#include<math.h>"引入math.h这个头文件,否则 ...
- JMS介绍:我对JMS的理解和认识
[ZT]JMS介绍:我对JMS的理解和认识 转自:http://blog.csdn.net/KimmKing/archive/2011/06/30/6577021.aspx,感谢作者KimmKing ...
- 51nod1203 JZPLCM 线段树 + 扫描线
不算很难的一道题 原题的数据虽然很小,但是我们不能欺负它,我们就要当$S[i] \leqslant 10^9$来做这题 最小公倍数 = 所有的质因数取可能的最大幂相乘 对于$> \sqrt S$ ...
- [APIO / CTSC2007]数据备份 --- 贪心
[APIO / CTSC 2007]数据备份 题目描述 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份. 然而数据备份的工作是枯燥乏味的,因此你想设计一个系统让不同的办公 ...
- SpringBoot 解决时区问题
SpringBoot 解决时区问题 1.在启动类加上 @PostConstruct void setDefaultTimezone() { TimeZone.setDefault(TimeZone.g ...
- USACO 2017 FEB Platinum nocross DP
题目大意 上下有两个长度为n.位置对应的序列A.B,其中数的范围均为1~n.若abs(A[i]-B[j]) <= 4,则A[i]与B[j]间可以连一条边.现要求在边与边不相交的情况下的最大的连边 ...
- [转]用 Jsp 的 Session 机制编写的购物车程序
一.构建的商品类 //写一个Goods类,并定义商品的各个属性,返回商品属性的方法,以及商品对象进行比较的方法//Goods.java package com.viita.Shop; public c ...
- Codeforces Beta Round #9 (Div. 2 Only) B. Running Student 水题
B. Running Student 题目连接: http://www.codeforces.com/contest/9/problem/B Description And again a misfo ...
- Nagios 监控mysqlserver具体实现过程
,之后在页面就能够看到监控效果了 參考文章:http://os.51cto.com/art/201409/452605.htm