[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 ...
随机推荐
- No packages marked for update
问题:用yum安装docker,更新yum存储时,报以下错误,导致yum坏了 [root@localhost yum.repos.d]# vi docker.repo [root@localhost ...
- [转]Java多线程
一.线程的生命周期及五种基本状态 关于Java中线程的生命周期,首先看一下下面这张较为经典的图: 上图中基本上囊括了Java中多线程各重要知识点.掌握了上图中的各知识点,Java中的多线程也就基本上掌 ...
- 深入理解Java虚拟机(类加载机制)
文章首发于微信公众号:BaronTalk 上一篇文章我们介绍了「类文件结构」,这一篇我们来看看虚拟机是如何加载类的. 我们的源代码经过编译器编译成字节码之后,最终都需要加载到虚拟机之后才能运行.虚拟机 ...
- postgresql计算2个日期之间工作日天数的方法
select date_part( 'day', minus_weekend(begin_date,end_date)) from table1 where name in ('a', 'b', 'c ...
- windows安装apache系统中无apache2服务解决方案
一直都是用WIN开发PHP,今天有用户反映SHUGUANG CMS在APACHE+PHP中不能正常运行,只好自己机器配置个环境测试(http://xz.8682222.com)遇到点小问题,搜索相关资 ...
- 廖雪峰Java14Java操作XML和JSON-1XML-1XML介绍
1.XML:可扩展标记语言(extensible Markup Language) 是一种数据表示格式 可以描述非常复杂的数据结构 用于存储和传输数据 1.1XML特点: 1.纯文本,默认utf-8编 ...
- C#一般处理程序设置和读取session(session报错“未将对象引用设置到对象的实例”解决)
登陆模块时,用到了session和cookie.在一般处理程序中处理session,一直报错.最后找到问题原因是需要调用 irequiressessionstate接口. 在ashx文件中,设置ses ...
- 第八章 Odoo 12开发之业务逻辑 - 业务流程的支持
在前面的文章中,我们学习了模型层.如何创建应用数据结构以及如何使用 ORM API 来存储查看数据.本文中我们将利用前面所学的模型和记录集知识实现应用中常用的业务逻辑模式. 本文的主要内容有: 以文件 ...
- JEECG-Boot 项目介绍——基于代码生成器的快速开发平台(Springboot前后端分离)
Jeecg-Boot 是一款基于代码生成器的智能开发平台!采用前后端分离架构:SpringBoot,Mybatis,Shiro,JWT,Vue&Ant Design.强大的代码生成器让前端和后 ...
- 【牛客挑战赛31D】 雷的打字机
题目 首先看到这个出现长度至少为\(2\)的回文子串 这就等价于不能出现两个连续且相同的字符 于是我们用概率生成函数来搞 设\(g_i\)表示\(i\)次操作后游戏没有结束的概率,\(f_{i,j}\ ...