当前位置:网站首页>【luogu P8352】小 N 的独立集(DP套DP)(性质)
【luogu P8352】小 N 的独立集(DP套DP)(性质)
2022-07-29 02:30:00 【SSL_TJH】
小 N 的独立集
题目链接:luogu P8352
题目大意
给你一棵树,然后每个点可以有 1~k 的点权。
然后对于每一种点权,形成的 n^k 棵树,最大权独立集的点权和为 x 的树有多少种。
对于每个 x 输出答案。
思路
笑死第一次做 DP 套 DP 推起来贼乱被爆杀。
(知道 DP 套 DP 的不难就知道)
里层 DP: f i , 0 / 1 f_{i,0/1} fi,0/1 当前点是 i i i, i i i 没选 / 选了。
然后对于一个点 u u u 的儿子 v v v 合并子树:
f u , 0 = max { f v , 1 , f v , 0 } f_{u,0}=\max\{f_{v,1},f_{v,0}\} fu,0=max{ fv,1,fv,0}
f u , 1 = f v , 0 + a u f_{u,1}=f_{v,0}+a_u fu,1=fv,0+au
然后外层就设 f u , i , j f_{u,i,j} fu,i,j 为 u u u 点 f u , 0 f_{u,0} fu,0 和 f u , 1 f_{u,1} fu,1 分别是 i , j i,j i,j 的方案数。
然后你就枚举一下类似背包的合并即可。
然后发现会 T, O ( n 4 k 4 ) O(n^4k^4) O(n4k4)。(合并 O ( n 3 ) O(n^3) O(n3))
考虑找点性质优化:
因为每次选了最多加 k k k,我们可以从 DP 的式子发现如果 f v , 0 ⩾ f v , 1 f_{v,0}\geqslant f_{v,1} fv,0⩾fv,1,那一定是只需要 f v , 0 f_{v,0} fv,0,那 f v , 1 f_{v,1} fv,1 的值就没有意义了。
而且如果是小于,差不会超过 k k k,那我们可以换个表示方法: f u , i , j f_{u,i,j} fu,i,j 为 u u u 点 f u , 0 , f u , 1 f_{u,0},f_{u,1} fu,0,fu,1 分别是 i , i + j i,i+j i,i+j 的方案数,那 j j j 就是 k k k 的级别的了。
然后转移就是 O ( n 2 k 4 ) O(n^2k^4) O(n2k4)(因为你按大小合并从 LCA 的角度计数是 n 2 n^2 n2 的)
至于转移细节,枚举 i , i i , j , j j i,ii,j,jj i,ii,j,jj 分别表示 f u , i , i i f_{u,i,ii} fu,i,ii 和 f v , j , j j f_{v,j,jj} fv,j,jj。
那转移到的就是 f u , i + j + j j , max ( 0 , i i − j j ) f_{u,i+j+jj,\max(0,ii-jj)} fu,i+j+jj,max(0,ii−jj)(因为你这里是要 i i i 不选儿子 j j j 选不选都可以),然后第三维也不难理解。
(第三维可以通过 max ( i + i i + j , i + j + j j ) − ( i + j + j j ) \max(i+ii+j,i+j+jj)-(i+j+jj) max(i+ii+j,i+j+jj)−(i+j+jj) 另一种方法,似乎更加利于理解)
代码
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#define ll long long
#define mo 1000000007
using namespace std;
const int N = 1005;
int n, K, sz[N];
vector <int> G[N];
ll f[N][N * 5][6], tmp[N * 5][6];
//1~5:正常,f1>f0,此时j记录f0
//f0不选,f1选
void dfs(int now, int father) {
sz[now] = K;
for (int i = 1; i <= K; i++) f[now][0][i] = 1;
for (int to = 0; to < G[now].size(); to++) {
int x = G[now][to];
if (x == father) continue; dfs(x, now);
for (int i = 0; i <= sz[now]; i++) for (int ii = 0; ii <= K; ii++) if (f[now][i][ii])
for (int j = 0; j <= sz[x]; j++) for (int jj = 0; jj <= K; jj++) if (f[x][j][jj]) {
(tmp[i + j + jj][max(ii - jj, 0)] += f[now][i][ii] * f[x][j][jj] % mo) %= mo;
}
sz[now] += sz[x];
for (int i = 0; i <= sz[now]; i++) for (int j = 0; j <= K; j++) f[now][i][j] = tmp[i][j], tmp[i][j] = 0;
}
}
int main() {
// freopen("nset.in", "r", stdin);
// freopen("nset.out", "w", stdout);
scanf("%d %d", &n, &K);
for (int i = 1; i < n; i++) {
int x, y; scanf("%d %d", &x, &y);
G[x].push_back(y); G[y].push_back(x);
}
dfs(1, 0);
for (int i = 1; i <= K * n; i++) {
ll re = 0;
for (int j = 0; j <= i && j <= K; j++)
(re += f[1][i - j][j]) %= mo;
printf("%lld\n", re);
}
return 0;
}
边栏推荐
猜你喜欢
第五天实验
Cloud development workers must go to work fishing and paddling wechat applet source code
Implement encapsulated public method global call in laravel framework
C language: Little Lele and Euclid
laravel框架中实现封装公共方法全局调用
ECCV 2022 | AirDet:无需微调的小样本目标检测方法
家庭亲戚关系计算器微信小程序源码
STP协议(生成树协议)
OSPF实验
Qt编写物联网管理平台48-特色功能设计
随机推荐
Wechat applet - Advanced chapter Lin UI component library source code analysis button component (II)
Thirty years of MPEG audio coding
解析机器人与人类情感共鸣的主观意识
用于校园流浪猫信息记录和分享的小程序源码/微信云开发中大猫谱小程序源码
Redis queue realizes second kill
C language: Little Lele and hexadecimal conversion
Catchadmin practical tutorial (IV) implementation of relevant functions of table components
New conch movie theme template m3.1 fully decrypted version multifunctional apple cmsv10 background adaptive theme open source fully decrypted version
Qt编写物联网管理平台48-特色功能设计
Implement encapsulated public method global call in laravel framework
自组织是管理者和成员的双向奔赴
idea替换所有文件中的内容
[error reporting] node:internal/modules/cjs/loader:936 [solution]
MPEG音频编码三十年
并发模式之异步回调Future模式
一款好看的iapp捐赠榜单源码
really time ntp服务启动命令
C language: judging letters
Mqtt routine
看机器人教育引领素质教育主流