【Luogu】P2465山贼集团(树形状压DP)
写了个70分暴力还挂了,第一遍提交只拿了十分……海星
首先建虚拟节点多叉树转成二叉,然后子集枚举DP
设g[x][i]是以x为根的子树内山贼集合i,x啥都不选也没贡献的时候的最大价值
f[x][i]是要求的答案
然后状压DP即可。
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cstdlib>
#define maxn 200
#define maxp 13
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Edge{
int next,to;
}; struct Pic{
Edge edge[maxn*];
int head[maxn*],num;
Pic(){num=;}
void add(int from,int to){
edge[++num]=(Edge){head[from],to};
head[from]=num;
}
}Old,New; int cst[maxn][maxn];
int tot;
int mon[<<maxp];
int dl[maxn],ndl[maxn*];
int f[maxn*][<<maxp];
int g[maxn*][<<maxp];
int cost[maxn][<<maxp];
int vl[<<maxp];
int n,p; void chan(int x,int fa){
int now=x;
for(int i=Old.head[x];i;i=Old.edge[i].next){
int to=Old.edge[i].to;
if(to==fa) continue;
if(ndl[now]==||(ndl[now]==&&dl[x]==)){
New.add(now,to);
ndl[now]++; dl[x]--;
}
else{
New.add(now,++tot);
now=tot;
New.add(now,to);
ndl[now]++; dl[x]--;
}
chan(to,x);
}
} void dfs(int x,int fa){
int lson=,rson=;
f[x][]=;
g[x][]=;
for(int i=New.head[x];i;i=New.edge[i].next){
int to=New.edge[i].to;
if(to==fa) continue;
if(lson==) lson=to;
else rson=to;
dfs(to,x);
}
if(x>n){
if(rson==){
for(int i=;i<(<<p);++i) f[x][i]=g[x][i]=f[lson][i];
return;
}
for(int i=;i<(<<p);++i){
for(int j=i;j;j=(j-)&i)
g[x][i]=max(g[x][i],f[lson][j]+f[rson][i^j]);
g[x][i]=max(g[x][i],f[lson][]+f[rson][i]);
f[x][i]=g[x][i];
}
}
else{
if(rson==){
for(int i=;i<(<<p);++i){
g[x][i]=f[lson][i];
f[x][i]=g[x][i]+mon[i];
}
for(int i=;i<(<<p);++i)
for(int j=i;j;j=(j-)&i)
f[x][i]=max(f[x][i],g[x][i^j]-cost[x][j]+mon[i]);
return;
}
for(int i=;i<(<<p);++i){
for(int j=i;j;j=(j-)&i)
g[x][i]=max(g[x][i],f[lson][j]+f[rson][i^j]);
g[x][i]=max(g[x][i],f[lson][]+f[rson][i]);
f[x][i]=g[x][i]+mon[i];
}
for(int i=;i<(<<p);++i)
for(int j=i;j;j=(j-)&i){
int costx=cost[x][j],state=i^j;
f[x][i]=max(f[x][i],g[x][state]+mon[i]-costx);
} }
} int main(){
memset(f,-/,sizeof(f));
memset(g,-/,sizeof(g));
g[][]=;
f[][]=;
n=read(),p=read();
tot=n;
for(int i=;i<n;++i){
int from=read(),to=read();
Old.add(from,to);
Old.add(to,from);
dl[from]++; dl[to]++;
}
for(int i=;i<=n;++i) dl[i]--;
for(int i=;i<=n;++i)
for(int j=;j<=p;++j) cst[i][j]=read();
int T=read();
while(T--){
int val=read(),cnt=read(),state=;
for(int i=;i<=cnt;++i){
int x=read();
state|=(<<(x-));
}
vl[state]+=val;
}
for(int i=;i<(<<p);++i)
for(int j=i;j;j=(j-)&i) mon[i]+=vl[j];
for(int i=;i<=n;++i)
for(int j=;j<(<<p);++j){
int costx=;
for(int k=;k<=p;++k)
if(j&(<<(k-))) costx+=cst[i][k];
cost[i][j]=costx;
}
chan(,);
dfs(,);
printf("%d\n",f[][(<<p)-]);
}
/*
9 3 1 2
1 3
1 4
2 5
3 6
3 7
3 8
6 9 */
【Luogu】P2465山贼集团(树形状压DP)的更多相关文章
- 『Tree nesting 树形状压dp 最小表示法』
Tree nesting (CF762F) Description 有两个树 S.T,问 S 中有多少个互不相同的连通子图与 T 同构.由于答案 可能会很大,请输出答案模 1000000007 后的值 ...
- 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp
题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...
- bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...
- 51nod 1673 树有几多愁——虚树+状压DP
题目:http://www.51nod.com/Challenge/Problem.html#!#problemId=1673 建一个虚树. 一种贪心的想法是把较小的值填到叶子上,这样一个小值限制到的 ...
- bzoj1402 Ticket to Ride 斯坦纳树 + 状压dp
给定\(n\)个点,\(m\)条边的带权无向图 选出一些边,使得\(4\)对点之间可达,询问权值最小为多少 \(n \leqslant 30, m \leqslant 1000\) 首先看数据范围,\ ...
- 刷题总结——树有几多愁(51nod1673 虚树+状压dp+贪心)
题目: lyk有一棵树,它想给这棵树重标号. 重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号. 这棵树的烦恼值为所有叶子节点的值的乘积. lyk想让这棵树的烦恼值最大,你只需输 ...
- bzoj 4006 管道连接 —— 斯坦纳树+状压DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 用斯坦纳树求出所有关键点的各种连通情况的代价,把这个作为状压(压的是集合选择情况)的初 ...
- 绿色计算大赛决赛 第二阶段 消息传递(斯坦纳树 状压dp+spfa)
传送门 Description 作为公司老板的你手下有N个员工,其中有M个特殊员工.现在,你有一个消息需要传递给你的特殊员工.因为你的公司业务非常紧张,所以你和员工之间以及员工之间传递消息会造成损失. ...
- 51nod1673 树有几多愁 - 贪心策略 + 虚树 + 状压dp
传送门 题目大意: 给一颗重新编号,叶子节点的值定义为他到根节点编号的最小值,求所有叶子节点值的乘积的最大值. 题目分析: 为什么我觉得这道题最难的是贪心啊..首先要想到 在一条链上,深度大的编号要小 ...
随机推荐
- 第一次发干货Observable.zip与Observable.forkJoin
在IT界已经混了5年了,5年中浏览了不少的网站,在上面查询自己想要的东西,解决工作中遇到的问题,心里总想有天自己能够有自己的博客,能给分享一些自己在生活中.工作中遇到的问题,让其他有类似经历的朋友能够 ...
- Nginx+php+mysql+wordpress搭建自己的博客站点
服务器环境要求Centos 6 或以上版本(由于我们的目标是半小时内搭建好,那就选简单yum安装)MySQL 5或更新版本Nginx 1或更新版本PHP 5 或更新版本 php-fpm 5或更新版本 ...
- 6-1 md5加密
1.导入hashlib模块,使用它的md5方法进行加密 import hashlib # import md5 python2 s = 'admin123' # .将字符串类型转换成byte类型才能加 ...
- thinkphp5 获取器的
获取器的作用是在获取数据的字段值后自动进行处理,例如,我们需要对状态值进行转换,可以使用: 1.数据库字段转换. class User extends Model { public function ...
- python__高级 : GC垃圾回收相关
python的垃圾回收机制是以引用计数为主,加上标记-清除,分代收集等辅助方式组成的,如果想打开gc功能,需要 import gc 模块 ,然后 gc.enable() 就打开了这个功能,关闭是 gc ...
- POJ:3421-X-factor Chains(因式分解)(全排列)
X-factor Chains Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7986 Accepted: 2546 Descr ...
- 【数据库】MySQL 从安装到命令
一, MySQL 的安装于配置 我是通过百度云盘的方式下载的.建议登录百度云终端,然后点击下面的链接,选择要安装的版本,解压安装. http://www.h2ero.cn/pan/share/17cd ...
- Android面试收集录 Android入门
1.Android的特点有哪些? 编程语言是Java或Kotlin,Android中的Java字节码是允许在Dalvik虚拟机上的 支持4大组件 Android内置了WebKit核心的浏览器,支持H5 ...
- 2139: road
把a[i], b[i]分开来排序 对应位置上的点连边 感性理解这是最小的 会连出若干个环 要使得若干个环连成大环 令a[i]向b[i - 1] 连边 易证一定能使图联通 感性理解这也是最小的 #inc ...
- 安装macports
Mac下面除了用dmg.pkg来安装软件外,比较方便的还有用MacPorts来帮助你安装其他应用程序,跟BSD中的ports道理一样.MacPorts就像apt-get.yum一样,可以快速安装些软件 ...