[BZOJ2427][HAOI2010]软件安装-tarjan缩点-树上dp
<题面>
这个题真伤人
之前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的更多相关文章
- bzoj 2427 [HAOI2010]软件安装 Tarjan缩点+树形dp
[HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2029 Solved: 811[Submit][Status][Dis ...
- [BZOJ2427][HAOI2010]软件安装(Tarjan+DP)
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1987 Solved: 791[Submit][Statu ...
- bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1053 Solved: 424[Submit][Statu ...
- 【BZOJ2427】[HAOI2010] 软件安装(缩点+树形DP)
点此看题面 大致题意: 有\(N\)个软件,每个软件有至多一个依赖以及一个所占空间大小\(W_i\),只有当一个软件的直接依赖和所有的间接依赖都安装了,它才能正常工作并造成\(V_i\)的价值.求在容 ...
- BZOJ2427: [HAOI2010]软件安装 tarjan+树形背包
分析: 一开始我以为是裸的树形背包...之后被告知这东西...可能有环...什么!有环! 有环就搞掉就就可以了...tarjan缩点...建图记得建立从i到d[i]之后跑tarjan,因为这样才能判断 ...
- [BZOJ2427][HAOI2010]软件安装(tarjan+树形DP)
如果依赖关系出现环,那么对于一个环里的点,要么都选要么都不选, 所以每个环可以当成一个点,也就是强连通分量 然后就可以构造出一颗树,然后树形背包瞎搞一下就行了 注意要搞一个虚拟节点当根节点 Code ...
- BZOJ 2427 /HAOI 2010 软件安装 tarjan缩点+树形DP
终于是道中文题了.... 当时考试的时候就考的这道题.... 果断GG. 思路: 因为有可能存在依赖环,所以呢 先要tarjan一遍 来缩点. 随后就进行一遍树形DP就好了.. x表示当前的节点.j表 ...
- 【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包
[BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为 ...
- 【BZOJ-2427】软件安装 Tarjan + 树形01背包
2427: [HAOI2010]软件安装 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 960 Solved: 380[Submit][Status ...
随机推荐
- Python全栈开发:生成随机数
#!/usr/bin/env python # -*- coding;utf-8 -*- import random def foo(args): """ :param ...
- python全栈开发:hashlib加密
哈希加密代码 #!/usr/bin/env python # -*- coding;utf-8 -*- """ 哈希加密模块中有很多算法,调用不同的算法执行不同的加密, ...
- sort的cmp函数
sort的cmp函数只能写return a>b;或者return a<b;
- 0902NOIP模拟测试赛后总结
rank1- rank3- rank4- rank10- rank16- 又考挂了.水平还是不行啊.和天皇差距太大了. 赛时A题的人好多啊.都是大佬.我一个正解都不会打……哭. T1想到dp和拓扑,然 ...
- 安装zabbix需要php的两个模块php-bcmath和php-mbstring(转)
安装zabbix需要php的两个模块php-bcmath和php-mbstring 原创 Linux操作系统 作者:甲骨文技术支持 时间:2018-02-24 18:35:24 1472 0 1. ...
- Android之shape属性简介和使用
1.shape标签简介 shape的形状,默认为矩形,可以设置为矩形(rectangle).椭圆形(oval).线性形状(line).环形(ring) ! 设置形状: <shape xmln ...
- php输出json,需要嵌套数组和对象问题
https://segmentfault.com/q/1010000009985295 $tmp = []; $tmp['id'] = 'aaa'; $tmp['name'] = 'bbb'; $tm ...
- Mybatis-构建 SqlSessionFactory
从 XML 中构建 SqlSessionFactory 每 一 个 MyBatis 的 应 用 程 序 都 以 一 个 SqlSessionFactory 对 象 的 实 例 为 核 心 . SqlS ...
- UNION All中ORDER By的使用
一个sql中,union了几个子查询.单独执行每个子查询都没问题,但union后执行,报ORA-00904: "xxx": invalid identifier关于union的使用 ...
- RQNOJ--160 竞赛真理(01背包)
题目http://www.rqnoj.cn/problem/160 分析:这是一个01背包问题,对于每一道题目,都有两个选择"做"或者"不做". 但是唯一不同的 ...