一、前言

  这道题同样来自于红书P142,作为树DP专题中的一道比较难的题目,A了一天左右的时间,看上去事实证明,这题的难度理我本身的实力还是有些太远了,于是正确的做法应该是分析一下题目之后进行解析什么的之后上VJ找AC代码,然后结合对状态转移方程的理解补出题解中没有提到或者。。搞错了的部分。于是看上去只有这种方法能够比较高效的进行自我扫盲什么的。作为一只萌新,成功的在刷这本书的过程中体验到了所谓“菜是原罪”这种奇妙的含义。

二、题意

  原题很长,但是大概的意思是,N各节点的一棵树,要求你找出,K大小的联通块中的权值最大值,以及所有能够构成最大值的K大联通块的构成方案数。

三、思路和坑

  这道题作为卡了我好久的一道题,看上去思路和前面一篇苹果树的题目有些奇妙的异曲同工之处——都是一个套路甚至代码可以互相改了用

  大概的思路是设置两个状态转移方程进行同步转移:

 1、DP【】【】用来保存“某节点,权值最大的,大小为J的联通块的组成数量”

 2、SUMM【】【】用来保存某节点权值最大的,大小为J的联通块的权值

  于是,我们可以子啊转移SUMM【】【】的时候把DP【】【】作为一个附属属性进行转移:当相同的时候进行加和,但是当有最大值出现的时候直接复制最大值的解决方案。

对于如何进行枚举实际上很容易想到的是0-1背包:
对于每个大小的子节点视为物品:权重是ARR[TAR],重量是尺寸。
之后认为背包容量就是总容量:SHARE,也就是前文提到的k。然后使用0-1背包特有的从上到下的方式进行状态转移。每个DFS中看上去有三重循环但是实际上由于每个节点只会被调用一次所以实际上时间复杂度是O(N*SHARE)。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define veci vector<int>
#define stai stack<int> const long long MAXN=;
const long long INF=<<;
const long long MOD=1e9+; veci G[MAXN];
ll arr[MAXN],dp[MAXN][MAXN],summ[MAXN][MAXN];
ll n,SHARE,ans,maxx,r; void dfs(int now,int last)
{
int len=G[now].size();
dp[now][]=;
summ[now][]=arr[now];
summ[now][]=;
for(int i=;i<len;++i)
{
int tar=G[now][i];
if(tar==last)continue;
dfs(tar,now); //使用0-1背包进行状态转移
for(int j=SHARE;j;j--)
{
for(int k=;k+j<=SHARE;++k)
{
ll newSum=summ[now][j]+summ[tar][k]; if(summ[now][j+k]==newSum)
{
dp[now][j+k]+=(dp[now][j]*dp[tar][k])%MOD;
dp[now][j+k]%=MOD;
}
if(summ[now][j+k]<newSum)
{
summ[now][j+k]=newSum;
dp[now][j+k]=(dp[now][j]*dp[tar][k])%MOD;
}
}
} }
if(maxx<summ[now][SHARE])
{
maxx=summ[now][SHARE];
ans=dp[now][SHARE];
}else if(maxx==summ[now][SHARE])
{
ans+=dp[now][SHARE];
ans%=MOD;
}
} void init()
{
cin>>n>>SHARE>>r;
ans=;maxx=-INF;
r=n-;
for(int i=;i<n;++i)
{
G[i].clear();
cin>>arr[i];
for(int j=;j<=SHARE;++j)
{
dp[i][j]=;
summ[i][j]=-INF;
}
}
while(r--)
{
int a,b;
cin>>a>>b;
G[a].push_back(b);
G[b].push_back(a);
}dfs(,-);
cout<<maxx<<" "<<ans<<"\n";
} int main()
{
cin.sync_with_stdio(false);
int ca;cin>>ca;
while(ca--)init(); return ;
}

最新文章

  1. SSH实战 &#183; 用spring框架下的hibernatetemplate的get方法出现的问题
  2. CentOS一键ftp
  3. java HashMap那点事
  4. 【腾讯Bugly干货分享】微信读书iOS性能优化
  5. junit单元测试中私有方法测试
  6. 线段树---Atlantis
  7. angular语法:Controller As
  8. 如何用Apache TCPMon来截获SOAP消息
  9. Java的Reference感觉很象C++的指针,但是区别是本质的
  10. AIM Tech Round (Div. 2) D. Array GCD dp
  11. 基于ARM-LINUX的温度传感器驱动-DS18B20
  12. Windows Phone 8 蓝牙编程
  13. bnuoj 20832 Calculating Yuan Fen(暴力模拟)
  14. Frank自动化测试
  15. zend server 和zend studio安装
  16. mybatis中使用if标签比较两个字符串是否相等
  17. C语言博客作业—字符数组
  18. 编写手机端自适应页面案例,springMVC代码,SpringMVC上传代码,去掉input框中原有的样式,使ios按钮没有圆角,css中的border-radius类似
  19. 【Unity编辑器】UnityEditor多重弹出窗体与编辑器窗口层级管理
  20. k8s小工具

热门文章

  1. spring ehcache 使用详解
  2. cf600E. Lomsat gelral(dsu on tree)
  3. WPF中的StackPanel、WrapPanel、DockPanel(转)
  4. Windows服务器高并发处理IOCP(完成端口)详细说明
  5. 性能调优--大事务与Alwayson 之间的关系
  6. linux打开文件数测试
  7. Producer &amp; Consumer
  8. hdu-3572 Task Schedule---最大流判断满流+dinic算法
  9. 【HDU1542】Atlantis (扫描线的经典运用)
  10. iOS Dispatch_sync 阻塞线程的原因