bzoj3090
树形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的更多相关文章
- bzoj3090: Coci2009 [podjela]
这个范围明显树包的 然而值并不滋磁 想了一会发现可以带一维当前子树用了多少边,搞定当前向上还能送多少 然后发现会有搞不定的情况,要向上传负数 每次都要重新初始化,负数强制要要 #include< ...
随机推荐
- Codeforces827D. Best Edge Weight
$n \leq 2e5,m \leq 2e5$的有边权图,对每条边问:不改其他边的情况下这条边最多能是多少使得他一定在所有最小生成树上,如果无穷大输出-1. 典型题+耗时题,CF上的绝望时刻..打VP ...
- JAVA中json转换为集合(对象)之间的相互转换
字符串转换为json对象: String strResult = RestUtil.getRestContent(url+"/service/peccancy/myOrderList&quo ...
- Codeforces 653D Delivery Bears【二分+网络流】
题目链接: http://codeforces.com/problemset/problem/653/D 题意: x个熊拿着相同重量的物品,从1号结点沿着路走到N号结点,结点之间有边相连,保证可以从1 ...
- 洛谷——P1047 校门外的树
P1047 校门外的树 题目描述 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0 ...
- makefile的语法及写法(二)
3 Makefile书写规则 -------------------------------------------------------------------------------- 规则包 ...
- 细说分布式Redis架构设计和踩过的那些坑
细说分布式Redis架构设计和踩过的那些坑_redis 分布式_ redis 分布式锁_分布式缓存redis 细说分布式Redis架构设计和踩过的那些坑
- 碧砚适合佳能328 4452 ICD520 4472 4450 硒鼓4700一体机墨盒4770
- C/C++实现bmp文件读写
之前知道点bmp图的格式,然后对8位操作过,然后今天弄了一下24位真彩色的. C++读取.旋转和保存bmp图像文件编程实现 主要是理解bmp文件的格式8/24位的区别 8位图有调色板,24位在文件头和 ...
- Win7 Windows Update更新的文件默认在哪个位置
C:\Windows\SoftwareDistribution\download
- List<Guid?> a = new List<Guid?>();
正常写法 泛型 类型 为 Guid? List<Guid?> a = new List<Guid?>(); Guid? b = null; Nullable<Guid&g ...