<题面>

这个题真伤人

之前Tarjan和树规都没学好,吃了不少亏,仔仔细细的搞了一天,收获颇丰

先来一个Tarjan的链接:$\mathbb{O}$

题目的数据比较友好:

$dp$不对:$\leq10$

$dp$对了Tarjan不对:$40$

都对了:$100$


接下来就是思路

首先观察题目。

$n$个点$n$条边,也许有环。

所以先以$0$为根节点(虚根,可以想象成”系统“,所有软件的依赖,无价值无内存),这样有一个好处,不用建边时特判,直接建就好了(无依赖是$0$)

额,你要问我怎么建,从被依赖的向依赖的指一个有向边

被依赖的$\Longrightarrow$依赖的,这样建好的图便于转移

建图结束,下面是个重头戏:缩点

这个题缩点极为简单,你会发现,环里的点已经互相依赖,不可能依赖其他的程序(除了虚根,我们暂不考虑)

这是我们就可以把它们打包安装。

首先Tarjan找出这个环,打个标记(我用的用新节点下标)

这样,我们把所有边扫一遍,凡是从环中的点出发的边起点都拽到新节点上,顺便把价值也统过去(别记重了)

最后把新节点连到虚根上。

还是很棒的吧?

然后是$dp$,就是很普通的树上背包。

$f_{i,j}$表示第$i$号节点使用$j$空间时的最大价值

写式子为敬:

$f_{i,j} = \max \limits_{w \leq j , s \in son_i} \{ f_{i,j-w}+f_{s,w} \}$

要从大往小$dp$,防止重复更新(01背包)

 #include <iostream>
#include <cstring>
#include <cstdio>
#define N 111
#define M 555
using namespace std; struct STAR{
int f,t,next;
}rs[N*N];int fl[*N],cnt=;
void add(int f,int t){
rs[cnt].f=f;
rs[cnt].t=t;
rs[cnt].next=fl[f];
fl[f]=cnt;
cnt++;
}
int pom,rom;
int val[*N],cost[*N];
struct mystack{
int st[*N],tp;
mystack(){
tp=;
memset(st,,sizeof st);
}
int top(){
return st[tp-];
}
void pop(){
tp--;
}
void push(int k){
st[tp]=k;
tp++;
}
bool empty(){
if(tp==)return true;
return false;
}
}sk;
void prerun(){
memset(fl,-,sizeof fl);
}
int dfn[*N],low[*N],dep=,bl[*N];
bool is_in[*N],is_v[*N],cut[*N];
void tarjan(int k){//cout<<" J "<<k<<endl;
dep++;
dfn[k]=low[k]=dep;
int t;
sk.push(k);
is_in[k]=;
for(int i=fl[k];i!=-;i=rs[i].next){
t=rs[i].t;
if(!dfn[t]){
tarjan(t);
low[k]=min(low[k],low[t]);
}
else{
if(is_in[t]){
low[k]=min(low[k],low[t]);
}
}
}
if(low[k]==dfn[k]){
if(sk.top()==k){
sk.pop();
is_in[k]=;
return;
}
int p=;
pom++;
do{
p=sk.top();
is_in[p]=;
bl[p]=pom;
sk.pop();
}while(p!=k);
}
}
int dp[*N][M];
void dfs(int k){
is_v[k]=;
dp[k][]=;
for(int i=fl[k];i!=-;i=rs[i].next){
int t=rs[i].t;
if(!is_v[t]){
dfs(t);
for(int w=rom;w>=;w--){
for(int m=;m<=rom;m++){
if(w-m>=)
dp[k][w]=max(dp[k][w],dp[k][w-m]+dp[t][m]);
}
}
}
}
for(int i=rom;i>=;i--)
if(i-cost[k]>=)
dp[k][i]=dp[k][i-cost[k]]+val[k];
else
dp[k][i]=;
}
int ans=;
int main(){
int a,beg;
prerun();
scanf("%d%d",&pom,&rom);beg=pom;
for(int i=;i<=pom;i++)
scanf("%d",&cost[i]);
for(int i=;i<=pom;i++)
scanf("%d",&val[i]);
for(int i=;i<=pom;i++){
scanf("%d",&a);
add(a,i);
}
for(int i=;i<=beg;i++){
if(!dfn[i])tarjan(i);
}
for(int i=;i<cnt;i++){
int fo=rs[i].f,to=rs[i].t;
if(bl[fo]!=){//cout<<"Cut"<<rs[i].f<<endl;
if(cut[fo]==){
val[bl[fo]]+=val[fo];
cost[bl[fo]]+=cost[fo];
cut[fo]=;
}
add(bl[fo],to); }
}
for(int i=;i<=beg;i++){
if(bl[i]!=){
is_v[i]=;
fl[i]=-;
}
}
for(int i=beg+;i<=pom;i++){
add(,i);
}
dfs();
for(int i=;i<=rom;i++){
ans=max(ans,dp[][i]);
}
printf("%d\n",ans);
return ;
}

Code

[BZOJ2427][HAOI2010]软件安装-tarjan缩点-树上dp的更多相关文章

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

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

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

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

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

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

  4. 【BZOJ2427】[HAOI2010] 软件安装(缩点+树形DP)

    点此看题面 大致题意: 有\(N\)个软件,每个软件有至多一个依赖以及一个所占空间大小\(W_i\),只有当一个软件的直接依赖和所有的间接依赖都安装了,它才能正常工作并造成\(V_i\)的价值.求在容 ...

  5. BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包

    分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...

  6. [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)

    如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...

  7. BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP

    终于是道中文题了.... 当时考试的时候就考的这道题.... 果断GG. 思路: 因为有可能存在依赖环,所以呢 先要tarjan一遍 来缩点. 随后就进行一遍树形DP就好了.. x表示当前的节点.j表 ...

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

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

  9. 【BZOJ-2427】软件安装 Tarjan + 树形01背包

    2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 960  Solved: 380[Submit][Status ...

随机推荐

  1. Python全栈开发:生成随机数

    #!/usr/bin/env python # -*- coding;utf-8 -*- import random def foo(args): """ :param ...

  2. python全栈开发:hashlib加密

     哈希加密代码 #!/usr/bin/env python # -*- coding;utf-8 -*- """ 哈希加密模块中有很多算法,调用不同的算法执行不同的加密, ...

  3. sort的cmp函数

    sort的cmp函数只能写return a>b;或者return a<b;

  4. 0902NOIP模拟测试赛后总结

    rank1- rank3- rank4- rank10- rank16- 又考挂了.水平还是不行啊.和天皇差距太大了. 赛时A题的人好多啊.都是大佬.我一个正解都不会打……哭. T1想到dp和拓扑,然 ...

  5. 安装zabbix需要php的两个模块php-bcmath和php-mbstring(转)

    安装zabbix需要php的两个模块php-bcmath和php-mbstring 原创 Linux操作系统 作者:甲骨文技术支持 时间:2018-02-24 18:35:24  1472  0 1. ...

  6. Android之shape属性简介和使用

    1.shape标签简介  shape的形状,默认为矩形,可以设置为矩形(rectangle).椭圆形(oval).线性形状(line).环形(ring)  ! 设置形状: <shape xmln ...

  7. php输出json,需要嵌套数组和对象问题

    https://segmentfault.com/q/1010000009985295 $tmp = []; $tmp['id'] = 'aaa'; $tmp['name'] = 'bbb'; $tm ...

  8. Mybatis-构建 SqlSessionFactory

    从 XML 中构建 SqlSessionFactory 每 一 个 MyBatis 的 应 用 程 序 都 以 一 个 SqlSessionFactory 对 象 的 实 例 为 核 心 . SqlS ...

  9. UNION All中ORDER By的使用

    一个sql中,union了几个子查询.单独执行每个子查询都没问题,但union后执行,报ORA-00904: "xxx": invalid identifier关于union的使用 ...

  10. RQNOJ--160 竞赛真理(01背包)

    题目http://www.rqnoj.cn/problem/160 分析:这是一个01背包问题,对于每一道题目,都有两个选择"做"或者"不做". 但是唯一不同的 ...