CodeForces1065F 树形dp
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的更多相关文章
- poj3417 LCA + 树形dp
Network Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 4478 Accepted: 1292 Descripti ...
- COGS 2532. [HZOI 2016]树之美 树形dp
可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...
- 【BZOJ-4726】Sabota? 树形DP
4726: [POI2017]Sabota? Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 128 Solved ...
- 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)
题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...
- 树形DP
切题ing!!!!! HDU 2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...
- POJ2342 树形dp
原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...
- hdu1561 The more, The Better (树形dp+背包)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...
- bzoj2500: 幸福的道路(树形dp+单调队列)
好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...
随机推荐
- 【python练习题】程序17
#题目:输入一行字符,分别统计出其中英文字母.空格.数字和其它字符的个数. s = input('请输入字符串:') alf = 0 space = 0 digi = 0 other = 0 for ...
- springcloud-app
https://gitee.com/vmaps/springcloud-app https://yq.aliyun.com/articles/329019?spm=a2c4e.11153940.blo ...
- CodeCraft-19 and Codeforces Round #537 Div. 2
D:即有不超过52种物品,求容量为n/2的有序01背包方案数.容易想到设f[i][j]为前i种物品已用容量为j的方案数,有f[i][j]=f[i-1][j-a[i]]*C(n/2-j+a[i],a[i ...
- 【XSY2759】coin DP 线性插值
题目描述 有\(n\)种面值不同的硬币,每种有无限个,且任意两个\((x,y)\)要么\(x\)是\(y\)的倍数,要么\(y\)是\(x\)的倍数. 你要取\(m\)元钱,问你有多少种不同的取法. ...
- prufer序列
介绍 其实是\(pr\ddot{u}fer\)序列 什么是prufer序列? 我们认为度数为\(1\)的点是叶子节点 有一颗无根树,每次选出编号最小的叶子节点,加到当前prufer序列的后面,然后删掉 ...
- synchronized 关键字解析
synchronized 关键字解析 同步锁依赖于对象,每个对象都有一个同步锁. 现有一成员变量 Test,当线程 A 调用 Test 的 synchronized 方法,线程 A 获得 Test 的 ...
- vim 高级编辑技巧
建议参考IBM官方文档https://www.ibm.com/developerworks/cn/linux/l-cn-tip-vim/ 重新输入以前输入过的某条命令Ctrl + r 全局替换格式:& ...
- Hdoj 2041.超级楼梯 题解
Problem Description 有一楼梯共M级,刚开始时你在第一级,若每次只能跨上一级或二级,要走上第M级,共有多少种走法? Input 输入数据首先包含一个整数N,表示测试实例的个数,然后是 ...
- 自学Python之路-Python网络编程
自学Python之路-Python网络编程 自学Python之路[第一回]:1.11.2 1.3
- 添加默认安全组规则-openstack
if [ "$1" ] ;then neutron security-group-rule-create --direction ingress --ethertype ipv4 ...