题目链接

  写了个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)的更多相关文章

  1. 『Tree nesting 树形状压dp 最小表示法』

    Tree nesting (CF762F) Description 有两个树 S.T,问 S 中有多少个互不相同的连通子图与 T 同构.由于答案 可能会很大,请输出答案模 1000000007 后的值 ...

  2. 【bzoj4006】[JLOI2015]管道连接 斯坦纳树+状压dp

    题目描述 给出一张 $n$ 个点 $m$ 条边的无向图和 $p$ 个特殊点,每个特殊点有一个颜色.要求选出若干条边,使得颜色相同的特殊点在同一个连通块内.输出最小边权和. 输入 第一行包含三个整数 n ...

  3. bzoj 4006 [JLOI2015]管道连接(斯坦纳树+状压DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4006 [题意] 给定n点m边的图,连接边(u,v)需要花费w,问满足使k个点中同颜色的 ...

  4. 51nod 1673 树有几多愁——虚树+状压DP

    题目:http://www.51nod.com/Challenge/Problem.html#!#problemId=1673 建一个虚树. 一种贪心的想法是把较小的值填到叶子上,这样一个小值限制到的 ...

  5. bzoj1402 Ticket to Ride 斯坦纳树 + 状压dp

    给定\(n\)个点,\(m\)条边的带权无向图 选出一些边,使得\(4\)对点之间可达,询问权值最小为多少 \(n \leqslant 30, m \leqslant 1000\) 首先看数据范围,\ ...

  6. 刷题总结——树有几多愁(51nod1673 虚树+状压dp+贪心)

    题目: lyk有一棵树,它想给这棵树重标号. 重标号后,这棵树的所有叶子节点的值为它到根的路径上的编号最小的点的编号. 这棵树的烦恼值为所有叶子节点的值的乘积. lyk想让这棵树的烦恼值最大,你只需输 ...

  7. bzoj 4006 管道连接 —— 斯坦纳树+状压DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4006 用斯坦纳树求出所有关键点的各种连通情况的代价,把这个作为状压(压的是集合选择情况)的初 ...

  8. 绿色计算大赛决赛 第二阶段 消息传递(斯坦纳树 状压dp+spfa)

    传送门 Description 作为公司老板的你手下有N个员工,其中有M个特殊员工.现在,你有一个消息需要传递给你的特殊员工.因为你的公司业务非常紧张,所以你和员工之间以及员工之间传递消息会造成损失. ...

  9. 51nod1673 树有几多愁 - 贪心策略 + 虚树 + 状压dp

    传送门 题目大意: 给一颗重新编号,叶子节点的值定义为他到根节点编号的最小值,求所有叶子节点值的乘积的最大值. 题目分析: 为什么我觉得这道题最难的是贪心啊..首先要想到 在一条链上,深度大的编号要小 ...

随机推荐

  1. JQuery实现子级选择器

    效果图如下: HTML代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  2. ios 苹果内购订单验证 --- php实现

    验证函数: function appleVerify($receipt_data,$orderId = 0) { /* * 21000 App Store不能读取你提供的JSON对象 * 21002 ...

  3. jQuery检测判断复选框是否被选中了的几种方法

    方法一:if ($("#checkbox-id")get(0).checked) {    // do something} 方法二:if($('#checkbox-id').is ...

  4. 12 new方法和单例、定制访问函数、装饰器

    new方法和单例.定制访问函数.装饰器 上节课作业解答 # 通过多重继承方法,分别定义出动物,人类,和和荷兰人三种类 class Animal(object): def __init__(self, ...

  5. 1014-34-首页15-计算原创微博的frame------计算cell的高度---计算 UILabel 的 CGSize 的方法

    一.总体思路: 在控制器中,每次拿到数据模型(请求了数据.加载新微博)的时候,就调用 - (NSArray *)stausFramesWithStatuses:(NSArray *)statuses, ...

  6. C# 控件置于最顶层、最底层、隐藏、显示

    控件置于最顶层.最底层 pictureBox1.BringToFront();//将控件放置所有控件最前端 pictureBox1.SendToBack();//将控件放置所有控件最底端 控件隐藏.显 ...

  7. 2、spring boot 配置文件

    配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoot自 ...

  8. react+redux状态管理实现排序 合并多个reducer文件

    这个demo只有一个reducer 所以合并reducer这个demo用不到 ,但是我写出来这样大家以后可以用到,很好用,管理多个reducer,因为只要用到redux就不会只有一个reducer所以 ...

  9. ClassNotFountException 与 NoClassDefineError

    一 知识准备 NoClassDefFoundError:正如它们的名字所说明的是一个错误 (Error),而ClassNotFoundException是一个异常.正如上一章节所说Exception和 ...

  10. 13 KNN背景分割器

    传统的前景背景分割方法有GrabCut,分水岭算法,当然也包括一些阈值分割的算法.但是这些算法在应用中往往显得鲁棒性较弱,达不到一个好的分割效果. 现代的背景分割算法融入了机器学习的一些方法来提高分类 ...