【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
传送门 题目大意: 给一颗重新编号,叶子节点的值定义为他到根节点编号的最小值,求所有叶子节点值的乘积的最大值. 题目分析: 为什么我觉得这道题最难的是贪心啊..首先要想到 在一条链上,深度大的编号要小 ...
随机推荐
- SpringBoot学习10:springboot整合mybatis
需求:通过使用 SpringBoot+SpringMVC+MyBatis 整合实现一个对数据库中的 t_user 表的 CRUD 的操作 1.创建maven项目,添加项目所需依赖 <!--spr ...
- Hibernate 提供session的工具类HibernateUtils
package cn.itcast.utils; import java.sql.Connection; import java.sql.SQLException; import org.hibern ...
- Python 初始—(高阶函数)
变量可以指向函数,函数的参数能接收变量, 将函数通过参数进行传递 def SetAbs(a,b,abs){ return abs(a)+abs(b) }
- lintcode_115_不同的路径 II
不同的路径 II 描述 笔记 数据 评测 "不同的路径" 的跟进问题: 现在考虑网格中有障碍物,那样将会有多少条不同的路径? 网格中的障碍和空位置分别用 1 和 0 来表示. ...
- Struts2基础入门
Struts2基础入门 创建一个web工程 0)导包并且创建一个核心配置文件 <?xml version="1.0" encoding="UTF-8"?& ...
- tp3.2 excel导出
//导出操作 function exportExcel($expTitle,$expCellName,$expTableData,$names,$width){ $xlsTitle = iconv(' ...
- Django 入门案例开发
Django是一个重量级的web开发框架,它提供了很多内部已开发好的插件供我们使用:这里不去描述 Django直接进入开发过程. Django入门案例分两部分:一.开发环境的配置:二.业务需求分析. ...
- JS - 给String.prototype添加replaceAll方法
String.prototype.replaceAll = function (targetStr, newStr) { var sourceStr = this.valueOf(); while ...
- Unity基础
unity unity 3大场景 Asset Scene Component Asset :资源导入导出 右击资源,选择导出Unity包 导入可以直接将只有复制到Asset文件夹 创建场景 File- ...
- php-安装与配置-未完待续2
一,准备工作 在入门指引中,我们已经知道PHP的3个应用领域,不同的场景,需要安装的东西是不同的.具体如下: 服务器端脚本,在通常情况下,需要三样东西:PHP 自身.一个 web 服务器和一个 web ...