当前位置:网站首页>P8352-[SDOI/SXOI2022]小N的独立集【dp套dp】
P8352-[SDOI/SXOI2022]小N的独立集【dp套dp】
2022-08-08 14:21:00 【QuantAsk】
正题
题目链接:https://www.luogu.com.cn/problem/P8352
题目大意
给出一棵树,每个点的权值是 [ 1 , k ] [1,k] [1,k]之间的一个数,对于 i ∈ [ 1 , n k ] i\in[1,nk] i∈[1,nk]求令这棵树的最大独立集权值为 i i i的方案数。
1 ≤ n ≤ 1000 , 1 ≤ k ≤ 5 1\leq n\leq 1000,1\leq k\leq 5 1≤n≤1000,1≤k≤5
解题思路
考虑我们求最大独立集时的 d p dp dp方程,设 f i , 0 / 1 f_{i,0/1} fi,0/1表示 i i i选/不选时的子树最大权值和。
注意到它总共有 n 2 k 2 n^2k^2 n2k2种状态,不能拿来dp套dp维护。
继续挖掘一下性质,若 f i , 0 ≥ f i , 1 f_{i,0}\geq f_{i,1} fi,0≥fi,1,那么 f i , 1 f_{i,1} fi,1显然没有用,若 f i , 0 + k ≤ f i , 1 f_{i,0}+k\leq f_{i,1} fi,0+k≤fi,1那么 f i , 0 f_{i,0} fi,0也没有用,因为我们可以显然父节点不选择更优。
所以我们可以强制 f i , 1 ∈ [ f i , 0 , f i , 0 + k ] f_{i,1}\in[f_{i,0},f_{i,0}+k] fi,1∈[fi,0,fi,0+k]这个范围,这样我们的状态数就只剩下 n k 2 nk^2 nk2种了。
设 g i , j , x g_{i,j,x} gi,j,x表示 f i , 0 = j , f i , 1 = j + x f_{i,0}=j,f_{i,1}=j+x fi,0=j,fi,1=j+x的方案数,然后 d p dp dp子树转移即可。
时间复杂度: O ( n 2 k 4 ) O(n^2k^4) O(n2k4)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1010,P=1e9+7;
struct node{
int to,next;
}a[N<<1];
int n,k,tot,siz[N],ls[N],ans[N*5],f[N][N*5][6],g[N*5][6];
void addl(int x,int y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
void Add(int &x)
{
x=(x>=P)?(x-P):x;}
void dfs(int x,int fa){
siz[x]=0;
for(int i=1;i<=k;i++)f[x][0][i]=1;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(y==fa)continue;dfs(y,x);
for(int a=0;a<=siz[x];a++){
for(int b=0;b<=k;b++){
if(!f[x][a][b])continue;
for(int c=0;c<=siz[y];c++)
for(int d=0;d<=k;d++){
int A=a+c+d,B=a+b+c;
B=B-A;if(B<0)B=0;
Add(g[A][B]+=1ll*f[x][a][b]*f[y][c][d]%P);
}
}
}
siz[x]+=siz[y]+k;
for(int a=0;a<=siz[x];a++)
for(int b=0;b<=k;b++)
f[x][a][b]=g[a][b],g[a][b]=0;
}
return;
}
int main()
{
// printf("%d\n",sizeof(f)>>20);
// freopen("2.in","r",stdin);
// freopen("2.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
addl(x,y);addl(y,x);
}
dfs(1,0);
for(int a=0;a<=siz[1];a++)
for(int b=0;b<=k;b++)
Add(ans[a+b]+=f[1][a][b]);
for(int i=1;i<=n*k;i++)
printf("%d\n",ans[i]);
return 0;
}
边栏推荐
- [Small Coder Study Room] [NOI Online 2020-2 Beginner Group] Finished: Abominable precision will make you burnt
- 小白大白读论文-关于EfficientNetV2论文的 疑问 与 总结
- 2022-08-07 The fifth group Gu Xiangquan study notes day31-collection-Map collection
- Shell Three Musketeers-----sed command
- QtWebassembly遇到的一些报错问题及解决方案
- 全网最全的AItium Designer 16下载资源与安装步骤
- 【SWT】创建自己的SWT组件
- 兔起鹘落全端涵盖,Go lang1.18入门精炼教程,由白丁入鸿儒,全平台(Sublime 4)Go lang开发环境搭建EP00
- a += 1 += 1为什么是错的?
- 「PHP基础知识」检测数据类型
猜你喜欢

译文推荐|深入解析 BookKeeper 协议模型与验证

基于Nodejs的医生预约平台的设计和实现

【个人总结】2022.8.7周结

HackTheBox | Horizontall

Harvard University smashes the field: DALL-E 2 is just a "glue monster", and the generation accuracy rate is only 22%
![[Redis] Redis installation and use of client redis-cli (batch operation)](/img/08/34f2c1cda8992e20ecd28b26d1e66a.png)
[Redis] Redis installation and use of client redis-cli (batch operation)

「PHP基础知识」检测数据类型

代码随想录笔记_动态规划_322零钱兑换

京东三面惨遭被虐,关于redis,高并发,分布式,问懵了

华为云弹性云服务器ECS使用【华为云至简致远】
随机推荐
【小码匠自习室】朋友的朋友不是朋友
更改默认打开应用程序设置
活动报名| StreamNative 受邀参与 ITPUB 在线技术沙龙
a += 1 += 1为什么是错的?
浏览器跨域方案,适用于本地调试接口(超简单)
【索引】图神经论文之GCN(持更)
mysql 查询一个字段为特定值,并且另一个字段的值出现两次的记录?
6. [opencv mouse callback event]
Pretraining Weekly Issue 56: Long Text Understanding, Instant Question Answering, Mask Self-Supervision
全网最全的PADS 9.5安装教程与资源包
idea 好工具
【小码匠自习室】叛逆的小孩,打死也不改
手把手教你设计一个全局异常处理器
bzoj 3624 [Apio2008]免费道路
Tsinghua | GLM-130B: An Open Bilingual Pre-training Model
textarea 禁止拖拽
树上距离为1子集修改
See how three years of CRUD programmers solve database deadlocks
暗恋云匹配匿名交友聊天系统开发
跟我一起了解云耀云服务器HECS【华为云至简致远】