博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
51Nod1353 树
阅读量:5262 次
发布时间:2019-06-14

本文共 1543 字,大约阅读时间需要 5 分钟。

51Nod1353 树

思路

我们定义\(dp[i][j]\)代表第i个点联通块大小为j的方案总数,也可以把它理解为等待分配(不确定归属)的联通块大小为j的方案总数。

那么每次转移我们就使用一个类似背包的东西来统计答案。

对于一个节点的每个儿子,我们只需要从大到小遍历所有可用的j_nowj_now上限就是所有遍历过的点子树大小的和)。然后再枚举这个儿子的j_son,那么显然我们就获得了很多第i个点联通块大小为j_son+j_now的方案。dp[i][j_son+j_now]+=dp[i][j_now]*dp[son][j_son]累计一下答案即可。需要注意的是,j_now需要从大往小遍历,因为反过来的话方案会算重(自己想一下01背包和完全背包)。另外,j_son是可以为0的,dp[son][0]代表son这个点只会包含在son子树内的联通块。所以对于每一个j_now都需要dp[now][j_now]*=dp[son][0]

在状态转移完后,对于每一个\(j\geq k\)我们都要执行操作dp[now][0]+=dp[now][j]。相当于分了一块大小为j的联通块。想一想就知道为什么了。

其实就是道树形依赖背包的模版。

代码

#include
#include
#include
#include
#include
#define ll long long#define maxn 2050#define mod (int)(1e9+7)using namespace std;ll dp[maxn][maxn],ans;int head[maxn],cnt,n,k,size[maxn];struct gg { int u,v,next;}side[maxn*2];void insert(int u,int v) { struct gg add={u,v,head[u]};side[++cnt]=add;head[u]=cnt;}void dfs(int now,int fa) { size[now]=1; dp[now][1]=1; for(int i=head[now];i;i=side[i].next) { int v=side[i].v;if(v==fa)continue; dfs(v,now); for(int j1=size[now];j1>=1;j1--) { for(int j2=1;j2<=size[v];j2++) { dp[now][j1+j2]+=(dp[now][j1]*dp[v][j2])%mod;dp[now][j1+j2]%=mod; } dp[now][j1]*=dp[v][0];dp[now][j1]%=mod; } size[now]+=size[v]; } for(int i=k;i<=size[now];i++)dp[now][0]+=dp[now][i],dp[now][0]%=mod;}int main() { scanf("%d%d",&n,&k); for(int i=1;i

1669439-20190914165735812-1614428342.jpg

转载于:https://www.cnblogs.com/GavinZheng/p/11519545.html

你可能感兴趣的文章
FileFilter文件过滤器
查看>>
selenium driver.close()与driver.quit()区别
查看>>
vue搭建骨架屏步骤配置
查看>>
判断程序是否已经启动的两种方法
查看>>
java启动项目报错,org.apache.catalina.lifecycleException..............以及解决方案
查看>>
vb.net ctype用法
查看>>
HDU 2639 Bone Collector II 背包k优解
查看>>
归并排序求逆序对
查看>>
HDU 1864最大报销额 01背包问题
查看>>
图论浅析--基础知识
查看>>
<数据结构与算法分析>读书笔记--最大子序列和问题的求解
查看>>
winform采用POST上传指定文件,并获取返回值
查看>>
一、Qt Creator的安装和hello world程序的编写
查看>>
C/C++ 关于大小端模式
查看>>
VueJs2.0建议学习路线
查看>>
An Algorithm
查看>>
导出Excel的几种方法
查看>>
赋值表达式也有值
查看>>
2013年下半年软件评測师(下午)试题分析与解答
查看>>
第一个项目--用bootstrap实现美工设计的首页
查看>>