分类
标签
2-SAT AC自动机 BFS CDQ dfs DP fail树 FFT FFT&NTT FWT hash KD-Tree KMP LCA SPFA STL Tarjan Treap Trie 主席树 乱搞 二分 二分图匹配 二分答案 二维SPFA 交互 位运算 其他 最小生成树 分块 区间DP 半平面交 博弈论 可持久化 可持久化Trie树 后缀数组 图库 平衡树 并查集 插头DP 数学 数论 无旋Treap 日记 暴力 权值树状数组 栈 树DP 树套树 树状数组 树贪心 概率DP 模拟 欧拉定理 点分治 状压DP 生成函数 矩阵乘 线性规划 线段树 组合 网络流 群论 莫比乌斯反演 计算几何 贪心 费用流 高斯消元
573 字
3 分钟
BZOJ 4027 [HEOI2015]兔子与樱花 贪心 dfs
Description
很久很久之前,森林里住着一群兔子。有一天,兔子们突然决定要去看樱花。兔子们所在森林里的樱花树很特殊。樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接,我们可以把它看成一个有根树结构,其中0号节点是根节点。这个树的每个节点上都会有一些樱花,其中第i个节点有c_i朵樱花。樱花树的每一个节点都有最大的载重m,对于每一个节点i,它的儿子节点的个数和i节点上樱花个数之和不能超过m,即son(i) + c_i <= m,其中son(i)表示i的儿子的个数,如果i为叶子节点,则son(i) = 0 现在兔子们觉得樱花树上节点太多,希望去掉一些节点。当一个节点被去掉之后,这个节点上的樱花和它的儿子节点都被连到删掉节点的父节点上。如果父节点也被删除,那么就会继续向上连接,直到第一个没有被删除的节点为止。
现在兔子们希望计算在不违背最大载重的情况下,最多能删除多少节点。 注意根节点不能被删除,被删除的节点不被计入载重。
Input
第一行输入两个正整数,n和m分别表示节点个数和最大载重 第二行n个整数c_i,表示第i个节点上的樱花个数 接下来n行,每行第一个数k_i表示这个节点的儿子个数,接下来k_i个整数表示这个节点儿子的编号
Output
一行一个整数,表示最多能删除多少节点。
Sample Input
10 4
0 2 2 2 4 1 0 4 1 1
3 6 2 3
1 9
1 8
1 1
0
0
2 7 4
0
1 5
0
Sample Output
1
题解
跑一遍dfs由下到上贪心就好
选最小的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> ch[2000005];
struct Tree{
int v;
}tree[2000005];
int m,ans;
int cmp(const int a,const int b){
return tree[a].v<tree[b].v;
}
void dfs(int rt){
for(int i=0;i<ch[rt].size();i++) dfs(ch[rt][i]);
sort(ch[rt].begin(),ch[rt].end(),cmp);
int i;
for(i=0;i<ch[rt].size();i++){
if(tree[rt].v+tree[ch[rt][i]].v-1<=m){
tree[rt].v+=tree[ch[rt][i]].v-1;
ans++;
}
else break;
}
}
int main()
{
//freopen("sakura.in","r",stdin);
//freopen("sakura.out","w",stdout);
int n,t,s;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)scanf("%d",&tree[i].v);
for(int i=0;i<n;i++){
scanf("%d",&t);
tree[i].v+=t;
while(t--){
scanf("%d",&s);
ch[i].push_back(s);
}
}
dfs(0);
printf("%d\n",ans);
//while(1);
}
BZOJ 4027 [HEOI2015]兔子与樱花 贪心 dfs
https://www.nekomio.com/posts/14/