题目

传送门 to HDU

题目概要
求一个树上的独立集,使得点权 aia_iai​ 求和为 xxx,并使得点权 bib_ibi​ 求和最大。

对于每个 x∈[1,m]x\in[1,m]x∈[1,m] 都要求出独立集的数量。

数据范围与提示
多组数据,组数 T≤20T\le 20T≤20 。

树的大小 n≤50n\le 50n≤50 但是 m≤1000m\le 1000m≤1000 。点权 ai≤ma_i\le mai​≤m 但是点权 bi≤106b_i\le 10^6bi​≤106 。

思路

你可以直接做树 dp\tt dpdp,但两棵子树的合并需要 O(m2)\mathcal O(m^2)O(m2) 跑一次背包,总共就是 O(nm2)\mathcal O(nm^2)O(nm2) 了。

只要涉及背包合并,根本不可能降低复杂度了。只能另辟蹊径。考虑 按顺序加入每个点。这样每个点的加入复杂度是 O(m)\mathcal O(m)O(m) 的。这种做法的唯一困难是,可能需要 2n2^n2n 记录选了哪些点。

但是你可以发现一些策略,使得记录的点数量极少。因为,对于一个已经考虑过的连通块,只需要记录边缘的点即可。自己手推一下,可以想到这样一个方案:先递归加入重儿子子树内的点,然后考虑加入自己。此时,自己的这个子树内只需要记录自己。然后递归加入所有轻儿子。

那么,任意时刻,有记录的点的最大数量是多少呢?用 T(n)T(n)T(n) 表示它,那么递归重儿子是至多 T(n−1)T(n-1)T(n−1) 的,并且递归后就被删除,不再产生更多影响。递归轻儿子前,要先记录自己的状态。但是轻儿子 return\tt returnreturn 之后,轻儿子内部就不再有需要记录状态的点了。所以多个轻儿子是独立的,最坏情况下
T(n)=T(n2)+1=log⁡nT(n)=T\left(\frac{n}{2}\right)+1=\log n T(n)=T(2n​)+1=logn

任意时刻最多记录了 log⁡n\log nlogn 个点,那么状态总数是 O(2log⁡nn)=O(n2)\mathcal O(2^{\log n}n)=\mathcal O(n^2)O(2lognn)=O(n2) 的。加入一个数字是 O(m)\mathcal O(m)O(m) 的,复杂度 O(n2m)\mathcal O(n^2m)O(n2m) 。

代码

你认为独立集数量很少?菊花图帮你获得约 2n−12^{n-1}2n−1 个!

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long int_;
inline int readint(){int a = 0; char c = getchar(), f = 1;for(; c<'0'||c>'9'; c=getchar())if(c == '-') f = -f;for(; '0'<=c&&c<='9'; c=getchar())a = (a<<3)+(a<<1)+(c^48);return a*f;
}
inline void writeint(const int_ &x){if(x > 9) writeint(x/10);putchar((x-x/10*10)^48);
}const int MaxN = 52;struct Edge{int to, nxt;
};
Edge e[MaxN<<1];
int head[MaxN], cntEdge;
void addEdge(int a,int b){e[cntEdge].to = b;e[cntEdge].nxt = head[a];head[a] = cntEdge ++;
}int siz[MaxN], son[MaxN];
void scan(int x,int pre = 0){siz[x] = 1, son[x] = 0;for(int i=head[x]; ~i; i=e[i].nxt)if(e[i].to != pre){scan(e[i].to,x);if(siz[e[i].to] > siz[son[x]])son[x] = e[i].to;siz[x] += siz[e[i].to];}
}const int LogN = 7;
const int MaxM = 5001;
const int infty = (1<<30)-1;
struct ZXY{int val; int_ cnt;void clear(){ val = -infty; }ZXY operator + (const int &t) const {ZXY c; c.val = val+t;c.cnt = cnt; return c;}void operator &= (const ZXY &t){if(val < t.val)val = t.val, cnt = 0;if(val == t.val)cnt += t.cnt;}
};
ZXY dp[1<<LogN][MaxM];
ZXY tmp[1<<LogN][MaxM];
int a[MaxN], b[MaxN]; // info
int nowId, id[MaxN] = {LogN};
void restore(int p){-- nowId; // deleted onefor(int x=0; x<(1<<nowId>>p); ++x)for(int y=0; y<(1<<p); ++y)for(int i=0; i<MaxM; ++i){tmp[(x<<p)|y][i] = dp[(x<<p<<1)|(1<<p)|y][i];tmp[(x<<p)|y][i] &= dp[(x<<p<<1)|y][i];}for(int S=0; S<(1<<nowId); ++S)for(int i=0; i<MaxM; ++i)dp[S][i] = tmp[S][i];
}
void dfs(int x,int pre = 0){id[x] = LogN; // clearif(son[x]) dfs(son[x],x);id[x] = nowId ++; // add itfor(int S=0; S<(1<<id[x]); ++S){int S_ = S|(1<<id[x]);for(int i=0; i<a[x]; ++i)dp[S_][i].clear();if((S>>id[son[x]]&1)|(S>>id[pre]&1))for(int i=a[x]; i<MaxM; ++i)dp[S_][i].clear();else for(int i=a[x]; i<MaxM; ++i)dp[S_][i] = dp[S][i-a[x]]+b[x];}if(son[x]) restore(id[x] = id[son[x]]);for(int i=head[x]; ~i; i=e[i].nxt){if(e[i].to == pre) continue;if(e[i].to == son[x]) continue;dfs(e[i].to,x);restore(id[e[i].to]);}
}int main(){dp[0][0].val = 0;dp[0][0].cnt = 1;for(int i=1; i<MaxM; ++i)dp[0][i].clear();int T = readint();for(int cas=1; cas<=T; ++cas){int n = readint();int m = readint();for(int i=1; i<=n; ++i){a[i] = readint();b[i] = readint();head[i] = -1;}cntEdge = 0;for(int i=1,x,y; i<n; ++i){x = readint(), y = readint();addEdge(x,y), addEdge(y,x);}scan(1), dfs(1);restore(id[1]); // kill allputchar('C'), putchar('a');putchar('s'), putchar('e');putchar(' '); writeint(cas);putchar(':'); putchar('\n');if(dp[0][1].val >= 0)writeint(dp[0][1].cnt);else putchar('0');dp[0][1].clear(); // for nextfor(int i=2; i<=m; ++i){putchar(' ');if(dp[0][i].val >= 0)writeint(dp[0][i].cnt);else putchar('0');dp[0][i].clear();}putchar('\n');}return 0;
}

后记

还有别的做法,比如建立 点分树。毕竟,只有点分树上的父子可能相邻。

[HDU6566]The Hanged Man相关推荐

  1. 树上连通有关背包:【BZOJ4182】shopping 【HDU6566】The Hanged Man

    选这两道题是因为这两道题都是树上背包,而且选的点的要求都与连通性有关,而且都是按 dfs 序 DP 来模拟不断加入物品,而且都能用树剖和点分治优化(不过优化的点一个跟子树大小有关一个跟深度有关),比较 ...

  2. 2018CCPC吉林赛区 hdu6555~hdu6566

    2018CCPC吉林赛区(重现赛)- 感谢北华大学 A 基础数论. #include<bits/stdc++.h> using namespace std;typedef long lon ...

  3. Ubuntu下RMI Server 抛出java.rmi.ConnectException: Connection refused to host: 127.0.0.1解决办法

    需要启动rmiregistry 参见 http://ubuntuforums.org/showthread.php?t=1278660 The actual reason is the rmiregi ...

  4. Guide: Solr performance tuning--转载

    原文地址:http://h3x.no/2011/05/10/guide-solr-performance-tuning Introduction I have for the last year be ...

  5. RocketMQ:消费端的消息消息队列负载均衡与重新发布机制源码解析

    文章目录 前言 流程解析 总结 前言 在上一篇博客中我们了解到,PullMessageService线程主要是负责从pullRequestQueue中获得拉取消息请求并进行请求处理的. PullMes ...

  6. 《DB 查询分析器》中断SQL语句的执行

    <DB 查询分析器>中断SQL语句的执行 马根峰 ( 广东联合电子收费股份有限公司, 广州 510300) 摘要     从事数据库查询.数据分析工作的人会经常遇到这样的情况,有些SQL语 ...

  7. 介绍计算机硬件的英语作文带翻译,介绍我家的英语作文(带翻译)

    介绍我家的英语作文(带翻译) I have a clean and warm home, or after school, please follow me to go to home and hav ...

  8. Linux 内核顶层Makefile 详解

    目录 前602行分析 make xxx_defconfig 过程 Makefile.build 脚本分析 make 过程 built-in.o 文件编译生成过程 make zImage 过程 前几章我 ...

  9. [渝粤教育] 广东-国家-开放大学 大学英语2

    1.He has_______since three days ago.(2 分) A.gone away B.gone C.left D.been away 2.What an interestin ...

最新文章

  1. 配置 php-fpm 监听的socket
  2. 思维 ---- 两两匹配问题 2021杭电多校第6场 E - Median
  3. R构建对数回归模型(Logarithmic Regression)
  4. 《Lua游戏开发实践指南》学习笔记3
  5. ubuntu 下安装nginx
  6. linux上利用crontab定时备份postgres数据库及文件到windows系统
  7. feign响应拦截_[Spring cloud 一步步实现广告系统] 11. 使用Feign实现微服务调用
  8. JVM命令查看与设置参数
  9. 从HEVC到通用视频编码的下一代视频压缩技术
  10. mybatis动态sql标签的使用
  11. python怎样连续输入两个数字_在python中生成连续的数字,同时输入不变
  12. 【笔记】《编写高质量代码:改善c#程序的157个建议》-第1章 基本语言要素(SamWang)...
  13. 成功的人不是最聪明的那个人,但绝对是一个交流很棒的人
  14. 【Typecho插件】Typecho百度主动推送插件
  15. 对偶式与反函数_对偶式和反函数什么关系,是不是都是一样,还是怎么回事啊,...
  16. js自执行函数(function(){})()前加个分号是什么意思?
  17. BZOJ1777: [Usaco2010 Hol]rocks 石头木头
  18. ubuntu20.04安装matlab2018b
  19. 简单使用Search()函数
  20. (48)性能测试——聚合报告

热门文章

  1. 营长来香港啦! 9位顶尖开发者、两大香港高校、现场编程, 共商区块链金融技术与落地!...
  2. 关于NodeJS中JSON5的相关配置和使用
  3. uniapp 微信小程序 open-type=“chooseAvatar“ 获取微信用户信息
  4. WordPress主题制作全过程(六):制作footer.php
  5. 学术报告系列(三) - 复杂海况无人艇虚实迁移学习方法
  6. 微电网|含分布式发电的微电网中储能装置容量优化配置(Matlab代码实现)
  7. MATLAB 批量处理文件
  8. STM32 发送字符串至淘晶驰串口屏显示到txt控件——避坑
  9. 拒绝弹窗!获取windows最高权限
  10. 医疗后服务的线上延续,随访是起点吗?