非常好的一道题,可以说是树形dp的一道基础题

首先不难发现,:如果我们把有关系的两个点用有向边相连,那么就会形成一个接近树的结构。如果这是一棵完美的树,我们就可以直接在树上打背包了

但是这并不是一棵完美的树,甚至并不是一棵树,因为:

首先,由于题中有n个点,还有n条边,所以有很大的几率出现环!

而且,如果出现了环,那么很有可能整个图并不连通,这样一来根本无法跑dp

所以我们要采取一些策略:

首先,对于出现环的情况,根据题意,此时环中的所有点要么都选,要么都不选,所以我们可以进行tarjan缩点,然后在新图上进行dp

至于整个图不连通的情况,我们可以虚拟一个超级原点向所有入度为0的点连边,这样就可以形成一棵真正的树,这样跑树形dp就可以了。

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;
struct Edge
{
int next;
int to;
}edge[105],e[105];
int head[105];
int h[105];
int cot=1;
int cnt=1;
void init()
{
memset(head,-1,sizeof(head));
memset(h,-1,sizeof(h));
cnt=1;
cot=1;
}
void adde(int l,int r)
{
e[cot].next=h[l];
e[cot].to=r;
h[l]=cot++;
}
void add(int l,int r)
{
edge[cnt].next=head[l];
edge[cnt].to=r;
head[l]=cnt++;
}
int n,m;
int w[105];
int v[105];
int nv[105];
int nw[105];
int posi[105];
int src_cnt=0;
int src_num[105];
int my_stack[105];
int dfn[105];
int low[105];
int dp[105][505];
int tot=0;
int ttop=0;
bool used[105];
int s[105];
void tarjan(int rt)
{
my_stack[++ttop]=rt;
dfn[rt]=low[rt]=++tot;
for(int i=head[rt];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(!dfn[to])
{
tarjan(to);
low[rt]=min(low[rt],low[to]);
}else if(!posi[to])
{
low[rt]=min(low[rt],dfn[to]);
}
}
if(dfn[rt]==low[rt])
{
int t=0;
src_cnt++;
while(t!=rt)
{
t=my_stack[ttop--];
posi[t]=src_cnt;
src_num[src_cnt]++;
nv[src_cnt]+=v[t];
nw[src_cnt]+=w[t];
}
}
}
void dfs(int x)
{
s[x]=nw[x];
dp[x][nw[x]]=nv[x];
for(int i=h[x];i!=-1;i=e[i].next)
{
int to=e[i].to;
dfs(to);
for(int j=s[x];j>=nw[x];j--)
{
for(int k=0;k<=s[to];k++)
{
if(j+k>m)
{
break;
}
dp[x][j+k]=max(dp[x][j+k],dp[x][j]+dp[to][k]);
}
}
s[x]+=s[to];
}
}
int main()
{
scanf("%d%d",&n,&m);
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&w[i]);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
}
for(int i=1;i<=n;i++)
{
int f;
scanf("%d",&f);
if(f)
{
add(f,i);
}
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].next)
{
int to=edge[j].to;
if(posi[to]!=posi[i])
{
adde(posi[i],posi[to]);
used[posi[to]]=1;
}
}
}
for(int i=1;i<=src_cnt;i++)
{
if(!used[i])
{
adde(0,i);
}
}
dfs(0);
int ans=0;
for(int i=0;i<=m;i++)
{
ans=max(ans,dp[0][i]);
}
printf("%d\n",ans);
return 0;
}

bzoj 2427的更多相关文章

  1. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜

    传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...

  2. [BZOJ 2427] 软件安装

    Link: BZOJ 2427 传送门 Solution: 只看样例的话会以为是裸的树形$dp$…… 但实际上题目并没有说明恰好仅有一个物品没有依赖项 因此原图可能由是由多棵树与多个图组成的 先跑一遍 ...

  3. bzoj 2427 软件安装 - Tarjan - 树形动态规划

    题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是 ...

  4. BZOJ 2427 & 分块裸题

    题意: 求区间内的众数,强制在线. SOL: 推荐一个大神犇的blog,讲的还是很好的(主要我喜欢他的代码风格(逃:http://www.cnblogs.com/JoeFan/p/4248767.ht ...

  5. BZOJ 2427: [HAOI2010]软件安装( dp )

    软件构成了一些树和一些环, 对于环我们要不不选, 要么选整个环. 跑tarjan缩点后, 新建个root, 往每个入度为0的点(强连通分量) 连边, 然后跑树dp( 01背包 ) ---------- ...

  6. bzoj 2427: [HAOI2010]软件安装

    Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和 ...

  7. BZOJ 2427 软件安装(强连通分量+树形背包)

    题意:现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现在有 ...

  8. bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp

    [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2029  Solved: 811[Submit][Status][Dis ...

  9. bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】

    一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp ...

随机推荐

  1. json对象转数组

    <script type="text/javascript"> var object = {"a":1,"b":2," ...

  2. MVC_Route层层深入

    1.前期准备 新建一个MVC项目,并添加Home和About两个控制器 在这两个控制器对应添加index页面 namespace Study_MVC_Route.Controllers { publi ...

  3. AJAX的来龙去脉(由来)-如何被封装出来的--ajax发送异步请求(四步操作)

    <黑马程序员_超全面的JavaWeb视频教程vedio\JavaWeb视频教程_day23_ajax> \JavaWeb视频教程_day23_ajax\day23ajax_avi\14.打 ...

  4. wx小程序-音频视频!

    1.音乐的启动跟暂停 dom里面图片切换的另一种方法 通过变量 改变路径 2.监听 在onload里面 3.定义了一个全局变量 然后在但页面中获取 app.js 单页面中 app.js 的三个生命周期

  5. 论文笔记系列-Neural Network Search :A Survey

    论文笔记系列-Neural Network Search :A Survey 论文 笔记 NAS automl survey review reinforcement learning Bayesia ...

  6. python读取两个文件并且判断是否一致

    ''' 判断两个文件是否相同,如果不同请指出第几行不相同 ''' def f1vsf2(name1,name2): f1 = open(name1) f2 = open(name2) count = ...

  7. 拦截RESTful API并做相应处理的方式

    ⒈使用Filter(过滤器) package cn.coreqi.security.filter; import org.springframework.stereotype.Component; i ...

  8. C++ 11 snippets , 2

    <1>auto ,initializer_list<T>,auto指向函数指针的简易,和typdef 定义的类型执行函数指针有多复杂. #include <iostrea ...

  9. tar命令加密压缩

    场景 Centos6下使用加密压缩,可以从A机器到B机器解压. 可用在kali上解压就不行. 命令 解包 tar zxvf FileName.tar 打包 tar czvf FileName.tar ...

  10. Pyperclip could not find a copy/paste mechanism for your system.

    sudo apt-get install xsel sudo apt-get install xclip pip install gtk to install the gtk Python modul ...