树形dp

有一个比较明显的dp状态是dp[i][j]表示当前i节点的子树已经满足且i剩下j元钱的最小操作次数,这样复杂度比较高状态数已经有O(n*x)的了,转移再来x,肯定不行。

我们考虑把状态和dp值交换一下,因为操作次数最多只有n-1次,这样可以大大降低dp状态数,于是我们设dp[i][j]表示i的子树已经满足了,且操作了j次,根节点最多能有多少多余的钱,这里可以是负数,我们自然希望子树内满足之后,根节点钱尽量多,这样可以支持其他节点,转移就是背包dp,tmp[i+j+1]=min(tmp[i+j+1],dp[u][i]+dp[v][j]),表示我们把v的钱转移到u上,那么这样又进行了一次操作,如果dp[u][j]>=0,说明u节点满足了,那么我们可以不用子树来支持,那么tmp[i+j]=min(tmp[i+j],dp[u][j]),这样是说不转移,然后那么v上的钱就不可能转移上来了,最后答案就是dp[1][j]>=0的j。

如果状态过多,有时我们可以考虑交换状态和dp值,这样可以降低复杂度

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = ;
int n, X;
vector<int> G[N];
int dp[N][N], tmp[N], v[N], size[N];
void dfs(int u, int last)
{
size[u] = ;
// for(int i = 0; i <= n; ++i) dp[u][i] = X - v[u];
dp[u][] = X - v[u];
for(int i = ; i < G[u].size(); ++i)
{
int v = G[u][i];
if(v == last) continue;
dfs(v, u);
memset(tmp, -0x3f3f, sizeof(tmp));
for(int j = ; j <= size[u]; ++j)
for(int k = ; k <= size[v]; ++k)
{
tmp[j + k + ] = max(tmp[j + k + ], dp[u][j] + dp[v][k]);
if(dp[v][k] >= ) tmp[j + k] = max(tmp[j + k], dp[u][j]);
}
size[u] += size[v];
for(int j = ; j <= size[u] + ; ++j) dp[u][j] = tmp[j];
}
}
int main()
{
scanf("%d%d", &n, &X);
for(int i = ; i <= n; ++i) scanf("%d", &v[i]);
for(int i = ; i < n; ++i)
{
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(dp, -0x3f3f, sizeof(dp));
dfs(, );
for(int i = ; i < n; ++i) if(dp[][i] >= )
{
printf("%d\n", i);
return ;
}
return ;
}

bzoj3090的更多相关文章

  1. bzoj3090: Coci2009 [podjela]

    这个范围明显树包的 然而值并不滋磁 想了一会发现可以带一维当前子树用了多少边,搞定当前向上还能送多少 然后发现会有搞不定的情况,要向上传负数 每次都要重新初始化,负数强制要要 #include< ...

随机推荐

  1. [luoguP2801] 教主的魔法(二分 + 分块)

    传送门 以为对于这类问题线段树都能解决,分块比线段树菜,结果培训完才知道线段树是一种特殊的分块方法,有的分块的题线段树不能做,看来分块还是有必要学的. 对于这个题,先分块,然后另开一个数组对于每个块内 ...

  2. ubuntu samba 配置简介

    Ubuntu 11.04下虚拟机Samba的共享配置详细步骤 一. Ubuntu 11.04下Samba的安装: $ sudo apt-get insall samba                 ...

  3. 【POJ3294】Life Forms(后缀数组,二分)

    题意: n<=100 len[i]<=1000 思路:这是一道论文题 ..]of longint; ch:..]of ansistring; n,n1,l,r,mid,last,i,j,m ...

  4. Google SPDY

    SPDY(读作“SPeeDY”)是Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验.SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强 ...

  5. 【转】php 之 array_filter、array_walk、array_map的区别

    [转]php 之 array_filter.array_walk.array_map的区别 原文:https://blog.csdn.net/csdnzhangyiwei/article/detail ...

  6. ArcGIS中Shapefile和Geodatabase坐标容差的问题

    转自原文 ArcGIS中Shapefile和Geodatabase坐标容差的问题 ArcGIS中,Shapefile文件是没有容差设置的,所以无论什么单位的坐标写入shapefile文件,都不存在容差 ...

  7. C# 获得图片的分辨率和大小

    double DPI = pictureBox1.Image.HorizontalResolution;//获得分辨率 gisoracle double w = 1.0 * pictureBox1.I ...

  8. zerorpc使用时报错:No handlers could be found for logger "zerorpc.channel"

    问题如题:安装方法参考 http://www.cnblogs.com/shengulong/p/7887586.html ,安装完后,使用时出现如题的错误 解决办法: 1.zerorpc本身依赖很多三 ...

  9. Android - 渠道号(vender)

    渠道号(vender) 本文地址: http://blog.csdn.net/caroline_wendy Android的apk公布,须要统计各个渠道(vendor)的激活数.就能够使用vendor ...

  10. python05-09

    一.lambda表达式 def f1(): return 123 f2 = lambda : 123 def f3 = (a1,a2): return a1+a2 f4 = lambda a1,a2 ...