首先tarjan缩点应该能看出来,然后我用topsort跑了个DAG上的一维dp,结果WA的很惨。

其实用DAG应该也能做,但是DAG强调整体顺序,而对一些局部问题,例如两个儿子怎么分配,是否给当前节点分配,那就太粗略化了,导致错误。

正确的姿势是把所有没有入度的点接到虚根上,因为tarjan缩完很可能是个森林,剩下的就是跑树形依赖的背包了。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<set>
#include<map>
using namespace std;
struct EDGE{
int ed,nex;
}edge[],edgec[];int num,numc,first[],firstc[];
int read(){
int sum=,f=;char x=getchar();
while(x<''||x>''){
if(x=='-') f=-;
x=getchar();
}while(x>=''&&x<=''){
sum=sum*+x-'';
x=getchar();
}return sum*f;
}
int n,m,w[],v[],dp[][];
int dfn[],low[],ord;
int stack[],top,ans,root;
int sccnum,bl[];
vector<int>scc[];
int wc[],vc[],du[];
bool ins[];
void add(int st,int ed){
edge[++num].ed=ed;
edge[num].nex=first[st];
first[st]=num;
}
void addc(int st,int ed){
edgec[++numc].ed=ed;
edgec[numc].nex=firstc[st];
firstc[st]=numc;
}
void tarjan(int x){
dfn[x]=low[x]=++ord;
stack[++top]=x;ins[x]=;
for(int i=first[x];i;i=edge[i].nex){
int y=edge[i].ed;
if(!dfn[y]){
tarjan(y);
low[x]=min(low[x],low[y]);
}else if(ins[y])
low[x]=min(low[x],dfn[y]);
}if(low[x]==dfn[x]){
sccnum++;int p;
do{
p=stack[top--];ins[p]=;
bl[p]=sccnum;scc[sccnum].push_back(p);
}while(x!=p);
}
} void dfs(int x){
//cout<<"fa="<<x<<endl;
/* for(int i=firstc[x];i;i=edgec[i].nex){
int y=edgec[i].ed;
cout<<y<<" ";
}*/
for(int i=firstc[x];i;i=edgec[i].nex){
int y=edgec[i].ed;
dfs(y);
for(int j=m-wc[x];j>=;j--)
for(int k=;k<=j;k++)
dp[x][j]=max(dp[x][j],dp[x][k]+dp[y][j-k]);
}
for(int i=m;i>=wc[x];i--) dp[x][i]=dp[x][i-wc[x]]+vc[x];
for(int i=;i<wc[x];i++) dp[x][i]=;
}
int main(){
/*freopen("9.in","r",stdin);
freopen("9.out","w",stdout);*/
/* memset(dp,0xcf,sizeof(dp));
dp[0]=0;*/
n=read();m=read();
for(int i=;i<=n;i++) w[i]=read();
for(int i=;i<=n;i++) v[i]=read();
for(int i=,D;i<=n;i++){
D=read();
if(!D) continue;
add(D,i);
}
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<=sccnum;i++)
for(int j=;j<scc[i].size();j++)
wc[i]+=w[scc[i][j]],vc[i]+=v[scc[i][j]];
for(int i=;i<=n;i++){
for(int j=first[i];j;j=edge[j].nex){
int y=edge[j].ed;
if(bl[i]==bl[y]) continue;
addc(bl[i],bl[y]);
// cout<<"St="<<bl[i]<<" Ed="<<bl[y]<<endl;
du[bl[y]]++;
}
}
root=sccnum+;
for(int i=;i<=sccnum;i++)
if(!du[i]) addc(root,i);
/* for(int i=1;i<=numc;i++)
cout<<edgec[i].ed<<" "<<edgec[i].nex<<endl;*/
/* for(int i=1;i<=sccnum;i++){
for(int j=0;j<scc[i].size();j++)
cout<<scc[i][j]<<" ";
cout<<endl;
}
for(int i=1;i<=sccnum;i++)
cout<<wc[i]<<" "<<vc[i]<<endl;*/
/* for(int i=1;i<=n;i++)
cout<<bl[i]<<" ";cout<<endl;
for(int i=1;i<=sccnum;i++)
cout<<wc[i]<<" "<<vc[i]<<endl;
for(int i=1;i<=numc;i++)
cout<<edgec[i].st<<" "<<edgec[i].ed<<endl;*/
dfs(root);
/* for(int i=0;i<=m;i++)
cout<<dp[root][i]<<" ";cout<<endl;*/
printf("%d",dp[root][m]);cout<<endl;
return ;
}

HAOI2010软件安装的更多相关文章

  1. BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP

    BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP 题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁 ...

  2. 【BZOJ2427】[HAOI2010]软件安装(动态规划,Tarjan)

    [BZOJ2427][HAOI2010]软件安装(动态规划,Tarjan) 题面 BZOJ 洛谷 题解 看到这类题目就应该要意识到依赖关系显然是可以成环的. 注意到这样一个性质,依赖关系最多只有一个, ...

  3. 洛谷 P2515 [HAOI2010]软件安装 解题报告

    P2515 [HAOI2010]软件安装 题目描述 现在我们的手头有\(N\)个软件,对于一个软件\(i\),它要占用\(W_i\)的磁盘空间,它的价值为\(V_i\).我们希望从中选择一些软件安装到 ...

  4. [BZOJ2427][HAOI2010]软件安装(Tarjan+DP)

    2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1987  Solved: 791[Submit][Statu ...

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

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

  6. Tarjan+树形DP【洛谷P2515】[HAOI2010]软件安装

    [洛谷P2515][HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得 ...

  7. 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包

    [BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...

  8. bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)

    2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1053  Solved: 424[Submit][Statu ...

  9. HAOI2010软件安装(树形背包)

    HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现 ...

  10. [HAOI2010]软件安装(Tarjan,树形dp)

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

随机推荐

  1. EasyUI_前台js_分页

    1.html: <table id="DataTb" title="客户信息" class="easyui-datagrid" sty ...

  2. 【原创】Linux基础之去掉windows中的\r

    linux换行为\n,windows换行为\r\n,windows环境编辑的shell脚本在linux下执行会报错: line 2: $'\r': command not found 查看 # cat ...

  3. vue项目中的登录鉴权

    用vue做一个简单的登录鉴权功能. 项目目录结构如下: Login 组件 登录成功后做本地存储和store存储,并进行跳转. Login.vue关键代码: async handleLogin(e) { ...

  4. C++ STL用法总结(持续更新)

    Vector 动态数组 https://www.cnblogs.com/zhonghuasong/p/5975979.html lower_bound&&upper_bound htt ...

  5. init是一个自定义方法名

    init是一个自定义方法名,用于初始化页面变量.上面的代码表示初始化方法是在当前网页加载后执行的(当浏览器打开网页时,触发窗口对象的onload方法,用上面的代码执行名为init的初始化方法).事实上 ...

  6. iptables防火墙操作-查看、配置、重启、关闭

    查看iptables端口配置 iptables -L -n --line-number iptables端口配置(不开通3389无法远程连接,不开通icmp无法ping) iptables -A IN ...

  7. FASTCGI/CGI

    在了解这两个协议之前,我们先谈一下动态网页 动态网页 是指跟静态网页相对的一种网页编程技术.静态网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了--除非你修改页面代码.而动态网 ...

  8. python面向对象、类、socket网络编程

    类和对象 python3统一了类与类型的概念:类==类型:从一组对象中提取相似的部分就是类:特征与技能的结合体就叫做对象: 类的功能: 初始实例化: 属性引用: 1.数据属性: 2.函数属性: 对于一 ...

  9. 一键登录怎么在iOS端实现?这篇文章教会你!

    在一键登录出现之前,市场上最常见的APP 注册登录方式主要有账号密码.短信验证及第三方登录.这几种方式看似常见且便捷,实则存在许多安全隐患,用户体验也相对较差.首先,短信验证码到达率低.用户操作繁琐且 ...

  10. Android | 自动调整文本大小的 TextViews

    简评:Auto-Sizing TextViews -- 当 TextView 的布局边界尺寸发生变化时,文本大小可以跟着自动缩放调整. 有时候我们需要 TextView 根据放入的内容来改变其文本大小 ...