2427: [HAOI2010]软件安装

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1053  Solved: 424
[Submit][Status][Discuss]

Description

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

但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j)。幸运的是,一个软件最多依赖另外一个软件。如果一个软件不能正常工作,那么它能够发挥的作用为0。

我们现在知道了软件之间的依赖关系:软件i依赖软件Di。现在请你设计出一种方案,安装价值尽量大的软件。一个软件只能被安装一次,如果一个软件没有依赖则Di=0,这时只要这个软件安装了,它就能正常工作。

Input

第1行:N, M  (0<=N<=100, 0<=M<=500)
      第2行:W1, W2, ... Wi, ..., Wn (0<=Wi<=M )
      第3行:V1, V2, ..., Vi, ..., Vn  (0<=Vi<=1000 )
      第4行:D1, D2, ..., Di, ..., Dn (0<=Di<=N, Di≠i )

Output

一个整数,代表最大价值。

Sample Input

3 10
5 5 6
2 3 4
0 1 1

Sample Output

HINT

 

Source

Day2

/*
开始一看这不是个基础的树型动规吗?(知道基础,但我不会啊),但是一看还有环嘞,苦逼了...
根据依赖关系可以画出来一张图,有三种可能的情况:
1.依赖关系构成一棵树。
2.依赖关系构成一个环。
3.依赖关系构成一个环下面吊着一棵树。
因为有2,3这些情况,所以要先有tarjan预处理一下,缩环为点,重新建图。
对于建好的图,跑一边树形背包即可,思想类似于01背包
f[x][tot]表示以x为根,容量为tot的最大收益。把x的各个子树看成物品
再枚举每个子树所分给的容量,tot从大到小转移。
*/
#include<iostream>
#include<cstdio>
#include<cstring> using namespace std;
int n,m,cnt,scc,ind,top,num;
int v[],w[];
int sv[],sw[];bool in_stack[];
int dfn[],low[],belong[];
int stack[],f[][],in[],head[],head2[];
struct node
{
int from;
int to;
int next;
}e[],e2[]; inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} inline void insert(int from,int to)
{
e[++num].from=from;
e[num].to=to;
e[num].next=head[from];
head[from]=num;
} inline void insert2(int from,int to)
{
in[to]=;
e2[++num].from=from;
e2[num].to=to;
e2[num].next=head2[from];
head2[from]=num;
} void Tarjan(int u)
{
int now=;
dfn[u]=low[u]=++ind;
stack[++top]=u;
in_stack[u]=;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(!dfn[v])
{
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in_stack[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
scc++;
while(now!=u)//统计环
{
now=stack[top--];in_stack[now]=;
belong[now]=scc;
sw[scc]+=w[now];
sv[scc]+=v[now];
}
}
}
void rebuild()//重建图
{
num=;
for(int x=;x<=n;x++)
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(belong[v]!=belong[x])
insert2(belong[x],belong[v]);
}
}
void dp(int x)
{
for(int i=head2[x];i;i=e2[i].next)
{
dp(e2[i].to);
for(int j=m-sw[x];j>=;j--)
{
for(int k=;k<=j;k++)//枚举子树的的限制。
f[x][j]=max(f[x][j],f[x][k]+f[e2[i].to][j-k]);
}
}
for(int j=m;j>=;j--)//完全背包
{
if(j>=sw[x])f[x][j]=f[x][j-sw[x]]+sv[x];
else f[x][j]=;
}
} int main()
{
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=;i<=n;i++)
{
int x=read();
if(x)insert(x,i);
}
for(int i=;i<=n;i++)
if(!dfn[i])Tarjan(i);
rebuild();
for(int i=;i<=scc;i++)
if(!in[i])
insert2(scc+,i);//这个地方要加1,因为根节点属于新的环。(不确定)
dp(scc+);
printf("%d\n",f[scc+][m]);
return ;
}

bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)的更多相关文章

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

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

  2. [BZOJ2427][HAOI2010]软件安装-tarjan缩点-树上dp

    <题面> 这个题真伤人 之前Tarjan和树规都没学好,吃了不少亏,仔仔细细的搞了一天,收获颇丰 先来一个Tarjan的链接:$\mathbb{O}$ 题目的数据比较友好: $dp$不对: ...

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

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

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

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

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

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

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

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

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

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

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

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

  9. bzoj2427: [HAOI2010]软件安装

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

随机推荐

  1. UVA - 10048 Audiophobia(Floyd求路径上最大值的最小)

    题目&分析: 思路: Floyd变形(见上述紫书分析),根据题目要求对应的改变判断条件来解题. 代码: #include <bits/stdc++.h> #define inf 0 ...

  2. linux安装java mysql tomcat 环境

    安装jdk: 1. 查看系统版本 uname -a 2.查看操作系统 cat  /proc/version 3.上传安装文件到指定目录   tar -zxvf jdkxxx. 4.修改配置文件  vi ...

  3. [bzoj1072][SCOI2007]排列(状态压缩DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1072 分析:看了题解才知道,状态的设计很巧妙,用余数表示,即f[i][j]表示二进制状 ...

  4. 用信号量及其PV操作处理实际问题

    43.现有3个生产者P1.P2.P3,他们都要生产橘子汁,每个生产者都已分别购得两种不同的原料,待购齐第三种原料后就可配制成橘子汁装瓶出售.有一供应商能源源不断的供应糖.水.橘子精,但每次只拿出一种原 ...

  5. Java使用JNA调用DLL库

    Java调用DLL方法有三种,JNI.JNA.JNative, 本文为JNA JNA为使用jna.jar包,下载地址:http://www.java2s.com/Code/Jar/j/Download ...

  6. 10、Java并发性和多线程-线程安全与不可变性

    以下内容转自http://ifeve.com/thread-safety-and-immutability/: 当多个线程同时访问同一个资源,并且其中的一个或者多个线程对这个资源进行了写操作,才会产生 ...

  7. 网卡MAC地址异常会导致无接受数据包,表现为只有发送没有接收

    遇到一个诡异的问题,一块4口博通千兆网卡中两个正常,两个怎么都没有接受,但是博通的程序网卡自检没有任何问题,最后发现是MAC地址的原因.需要将地址改为正常MAC方可正常通讯. 感觉应该是交换机丢弃了M ...

  8. _deque实现

    /* deque是一种双向开口的连续线性空间,可以在头尾两端分别做元素的插入和删除操作 常用接口:back(), front(), push_back(), pop_back(), push_fron ...

  9. HDOJ--1285--确定比赛名次

    确定比赛名次 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  10. linux程序设计——运行SQL语句(第八章)

    8.3    使用C语言訪问MySQL数据 8.3.3 运行SQL语句 运行SQL语句的主要API函数被恰当的命名为: int mysql_query(MYSQL *connection, const ...