题目

Description

今天Karen要去买东西。

一共有 \(n\) 件物品,每件物品的价格为\(c_i\),同时每件物品都有一张优惠券,可以对这件物品减价 \(d_i\) . 使用第 \(i\) 件物品的优惠券的条件是买这件物品并且使用了第 \(x_i\) 张优惠券。现在给出Karen带的钱数 \(b\) ,问最多能买几件物品。

Input

第一行两个整数 \(n\le 5\times 10^3 , b\le 10^9\) 。

接下来 \(n\) 行中第 \(i\) 行,首先有两个整数 \(c_i,d_i\le 10^9\) 。对于 \(i>1\) 有第三个整数 \(1\le x_i<i\) 。

Output

一行,输出最多能买的物品个数。

Sample Input

样例1:

6 16

10 9

10 5 1

12 2 1

20 18 3

10 2 3

2 1 5

样例2:

5 10

3 1

3 1 1

3 1 2

3 1 3

3 1 4

Sample Output

样例1:

4

样例2:

5

Hint

样例1: 买1,3,4号物品,用优惠券;买6号物品,不用优惠券

样例2:买所有的的物品,用优惠券

分析

由于每个物品只有一件,我们可以把问题转化成求买 \(k\) 个物品至少需要多少钱,最后再统计最多可以买多少个。

由于有 \(1\le x_i<i\) ,所以优惠券的使用条件构成了一棵树。现在问题是如何在这颗树上求解。

注意到如果一个点不用优惠券,那么子树中所有点都不能用,所以设状态:

\(f[x][i][0,1]\) 表示以 \(x\) 为根的子树中买 \(i\) 件物品,是否可以用优惠券(0不能,1能),那么可以通过子树的信息来更新当前点:

\[f[x][i+j][0]=\min \{f[u][i][0]+f[v][j][0],u,v\in \text{subtree}(x)\} \\
f[x][i+j][1]=\min \{f[u][i][1]+f[v][j][1],f[u][i][0]+f[v][j][1],u,v\in \text{subtree}(x)\} \\
\]

即如果当前点不可用优惠券,那么子树都不能用。如果当前点用优惠券,那么子树可用可不用。

这样\(f[\text{root}][k][1]\)就是我们要求的东西。

这样做似乎是\(O(n^3)\)的呢!我们实际上是枚举子树中的点对,所以可以不断地把点合并进当前点中,就可以做到\(n^2\)级别了。

循环的时候要从后往前,否则无法保证每件物品只买一次。

代码

#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long giant;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=5e3+10;
const giant inf=1e13;
int n,bud;
giant f[maxn][maxn][2];
vector<int> g[maxn];
void add(int x,int y) {g[x].push_back(y);}
void Min(giant &x,giant y) {x=min(x,y);}
int dfs(int x) {
int sz=1;
for (int v:g[x]) {
int vs=dfs(v);
for (int j=sz;j>=0;--j) {
for (int i=vs;i>=0;--i) {
Min(f[x][i+j][0],f[x][j][0]+f[v][i][0]);
Min(f[x][i+j][1],f[x][j][1]+f[v][i][1]);
}
}
sz+=vs;
}
for (int i=0;i<=n;++i) Min(f[x][i][1],f[x][i][0]);
return sz;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
n=read(),bud=read();
for (int i=1;i<=n;++i) for (int j=0;j<=n;++j) for (int k=0;k<2;++k) f[i][j][k]=inf;
for (int i=1;i<=n;++i) {
f[i][0][0]=0,f[i][1][0]=read(),f[i][1][1]=f[i][1][0]-read();
if (i>1) add(read(),i);
}
dfs(1);
int ans=0;
for (int i=1;i<=n;++i) if (f[1][i][1]<=bud) ans=i;
printf("%d\n",ans);
return 0;
}

CF816E-Karen and Supermarket的更多相关文章

  1. [CF816E] Karen and Supermarket1 [树形dp]

    传送门 - > \(CF816E\) Karen and Supermarket 题意翻译 在回家的路上,凯伦决定到超市停下来买一些杂货. 她需要买很多东西,但因为她是学生,所以她的预算仍然很有 ...

  2. Codeforces 815C Karen and Supermarket 树形dp

    Karen and Supermarket 感觉就是很普通的树形dp. dp[ i ][ 0 ][ u ]表示在 i 这棵子树中选择 u 个且 i 不用优惠券的最小花费. dp[ i ][ 1 ][ ...

  3. CF815C Karen and Supermarket

    题目链接 CF815C Karen and Supermarket 题解 只要在最大化数量的前提下,最小化花费就好了 这个数量枚举ok, dp[i][j][1/0]表示节点i的子树中买了j件商品 i ...

  4. CF815C Karen and Supermarket [树形DP]

    题目传送门 Karen and Supermarket On the way home, Karen decided to stop by the supermarket to buy some gr ...

  5. E. Karen and Supermarket

    E. Karen and Supermarket time limit per test 2 seconds memory limit per test 512 megabytes input sta ...

  6. Codeforces Round #419 (Div. 1) C. Karen and Supermarket 树形DP

    C. Karen and Supermarket     On the way home, Karen decided to stop by the supermarket to buy some g ...

  7. codeforces 815C Karen and Supermarket

    On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...

  8. codeforces round #419 E. Karen and Supermarket

    On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...

  9. Codeforces 815 C Karen and Supermarket

    On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...

  10. 【Codeforces 815C】Karen and Supermarket

    Codeforces 815 C 考虑树型dp. \(dp[i][0/1][k]\)表示现在在第i个节点, 父亲节点有没有选用优惠, 这个子树中买k个节点所需要花的最小代价. 然后转移的时候枚举i的一 ...

随机推荐

  1. 2017-2018-1 20155306 20155315 《信息安全技术》实验二、Windows口令破解

    在网络界,攻击事件发生的频率越来越高,其中相当多的都是由于网站密码泄露的缘故,或是人为因素导致,或是口令遭到破解,所以从某种角度而言,密码的安全问题不仅仅是技术上的问题,更主要的是人的安全意识问题. ...

  2. 20155334 实验三 敏捷开发与XP实践

    实验内容 XP基础 XP核心实践 相关工具 实验要求 没有Linux基础的同学建议先学习<Linux基础入门(新版)><Vim编辑器> 课程 完成实验.撰写实验报告,实验报告以 ...

  3. 238. Product of Array Except Self(对O(n)和递归又有了新的理解)

    238. Product of Array Except Self     Total Accepted: 41565 Total Submissions: 97898 Difficulty: Med ...

  4. RHCSA-day4

    硬盘分区 1.硬盘的物理组成 硬盘实际上是由很多的盘片.磁臂.磁头与主轴马达所组成的. 那么实际的数据当然是写在具有磁性物质的盘片上了.数据的读写主要是通过在磁臂上的磁头来完成的.实际运转时,主轴马达 ...

  5. STM32运行FreeRTOS出现prvTaskExitError错误死机

    文件port.c prvTaskExitError();任务退出错误,一个可能在任务里面写了return,另一个可能任务切换退出问题,入栈和出栈的时候出了问题. static void prvTask ...

  6. Spark 序列化问题

    在Spark应用开发中,很容易出现如下报错: org.apache.spark.SparkException: Task not serializable at org.apache.spark.ut ...

  7. 逆向某停车app(原创)

    最近一直在做python开发的事情,信息安全方面做得很少,也是"蛋蛋"的忧伤呀.今天有朋友请我帮忙,将一个app里的文字和图标替换一下,花了一下午和一晚上的时间搞了一下,主要是图标 ...

  8. Linux 安装Zookeeper<集群版>(使用Mac远程访问)

    阅读本文需要先阅读安装Zookeeper<准备> 一 架构细节 zookeeper集群根据投票选举的机制 选出leader和follower zookeeper集群节点建议是奇数 这里我准 ...

  9. Vue2 v-bind:href 中如何使用过滤器

    <a class="topic_title" v-bind:href="info.id|getTitleHref" v-bind:title=" ...

  10. android点击事件的四种方式

    android点击事件的四种方式 第一种方式:创建内部类实现点击事件 代码如下: package com.example.dail; import android.text.TextUtils; im ...