http://codeforces.com/problemset/problem/1065/F

你有一棵带有n个结点的树,根是结点1。有一个标记,最初在根结点处。你可以将标记移动到其他结点处。假设标记当前所在结点为v,你可以做出以下两种操作:

将标记移动到v子树的任一叶子处。

如果是结点v为叶子,则将标记向根移动不超过 k 次。换句话说,如果 h(v) 为结点 v 的深度 (根的深度为0),你可以将其移动到顶点 to ( to 为 v 祖先) 并且 h(v)−k≤h(to)。

根不是叶子(即使它的度数是 )。计算最多能访问多少叶子。

输入格式:

第一行包含两个整数 n 和 k (<k<n≤^) --- 树中的顶点数和向上移动的限制。

第二行包含 n-1个整数 第i个整数表示结点i+1的父亲 输入保证树合法,根为1。

输出格式:

输出一个整数,表示可以访问的最大叶子数。

题意

把问题想难了,想在树dp上同时用树状数组维护,然后一波操作把自己骚死了

一个显然的贪心思想是从1开始将所有可以拿的结点全部拿完之后返回1,然后进入下一个结点,这样每次遍历到根节点的结果都是最优的,判断拿结点的方法用树dp操作一下,用dfs进行预处理即可。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],tot;
void init(){
memset(head,-,sizeof(int) * (N + ));
tot = ;
}
void addedge(int u,int v){
edge[tot].next = head[u];
edge[tot].to = v;
head[u] = tot++;
}
int dp[maxn],dp2[maxn];
void dfs(int t){
if(head[t] == -){
dp[t] = ; dp2[t] = K;
return;
}
dp[t] = ,dp2[t] = ;
for(int i = head[t]; ~i ; i = edge[i].next){
int v = edge[i].to;
dfs(v);
if(dp2[v]) dp[t] += dp[v];
dp2[t] = max(dp2[t],dp2[v] - );
}
}
int sum = ;
void DP(int t,int ans){
if(head[t] == -){
ans++;
sum = max(sum,ans);
}
for(int i = head[t]; ~i; i = edge[i].next){
int v = edge[i].to;
if(dp2[v]){
DP(v,ans + dp[t] - dp[v]);
}else{
DP(v,ans + dp[t]);
}
}
}
int main()
{
Sca2(N,K); init();
for(int i = ; i <= N; i ++){
int u; Sca(u);
addedge(u,i);
}
int root = ;
dfs();
DP(,);
Pri(sum);
#ifdef VSCode
system("pause");
#endif
return ;
}

CodeForces1065F 树形dp的更多相关文章

  1. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  2. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  3. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  4. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  5. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  6. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  7. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  8. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

  9. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

随机推荐

  1. 离线安装Python包hickle,easydict

    安装hickle source: https://github.com/telegraphic/hickle 1. cd to your downloaded hickle directory 2.  ...

  2. Linux下的好用的编辑软件Remarkable

    Linux下的好用的编辑软件Remarkable最近着手开始学习Linux,就想着找一款好用的编辑器作笔记,在网上爬了些贴选择了Remarkable.官网崩了,有没有梯子,废了好大力气才装好.于是把资 ...

  3. x = x &(x-1)

    判断一个数(x)的二进制含有几个1 int func(x) { ; while(x) { countx ++; x = x&(x-); } return countx; } 假定x = 999 ...

  4. HTML查漏补缺 【未完】

    1.命名锚 HTML 链接 - name 属性 name 属性规定锚(anchor)的名称. 您可以使用 name 属性创建 HTML 页面中的书签. 书签不会以任何特殊方式显示,它对读者是不可见的. ...

  5. SHELL编程综合练习

    SHELL编程综合练习1 一. 实验准备(预防抄袭,此步必做) 请将命令提示符设为你的学号:输入PS1=你的学号_,即学号之后跟下划线,例如PS1=110015_, 回车执行 如发现命令提示符和你的学 ...

  6. Ionic3报错Error: Uncaught (in promise): Error: StaticInjectorError

    ERROR Error: Uncaught (in promise): Error: StaticInjectorError[Geolocation]: StaticInjectorError[Geo ...

  7. Win10 GodMode

    Win10 GodMode 文件夹命名示例: GodMode.{ED7BA470-8E54-465E-825C-99712043E01C} {ED7BA470-8E54-465E-825C-99712 ...

  8. [loj6388] 「THUPC2018」赛艇 / Citing

    Description ​ 给你一个\(~n \times m~\)的\(~01~\)矩阵,一个人在这个矩阵中走了\(~k~\)步,每一次都往四联通方向中的一个走一步.给定这个人每一步走的方向,已知这 ...

  9. android Button 属性

    Android中button 继承了TextView组件. 可以这么用: final TextView tv = new Button(getApplicationContext()); tv.set ...

  10. LVM-COW写实备份

    [root@localhost ~]# fdisk -l /dev/sdb /dev/sdc | grep "LVM"/dev/sdb1 1 9660 77593918+ 8e L ...