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 - 10603 Fill(BFS求最小值问题)

    题目: 给出三个杯子(没有刻度线)的容量,起初之后第三个杯子是满的,其他的两个杯子是空的,容量分别是a.b.c.问最少需要倒多少升水才能让某一个杯子中的水有d升?如果不能恰好做到d升,就让某一个杯子里 ...

  2. 网络配置:IP+NETMASK+GATEWAY+DNS

    1.  IP IP地址(英语:Internet Protocol Address)是一种在Internet上的给主机编址的方式,也称为网际协议地址.常见的IP地址,分为IPv4与IPv6两大类. IP ...

  3. linux网络不通,如何解决

    (Network is unreachable)表示网络不可达,先ping一个外网网段检测是否通畅,(如ping不通)检查防火墙是否阻挡,网关是否正确,再检查网卡配置文件(注:网卡配置顺序错误,也可导 ...

  4. Java基础学习总结(84)——Java面向对象六大原则和设计模式

    面向对象六大原则 在此之前,有一点需要大家知道,熟悉这些原则并不是说你写出的程序就一定灵活.清晰,只是为你优秀的代码之路铺上了一层栅栏,在这些原则的指导下,你才能避免陷入一些常见的代码泥沼,从而让你写 ...

  5. Leetcode 115.不同的子序列

    不同的子序列 给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串.(例 ...

  6. hdu 1853 KM算法

    #include<stdio.h> #include<math.h> #include<string.h> #define N 200 #define inf 99 ...

  7. codevs2486 太鼓达人

    题目描述 Description 七夕祭上,Vani牵着cl的手,在明亮的灯光和欢乐的气氛中愉快地穿行.这时,在前面忽然出现了一台太鼓达人机台,而在机台前坐着的是刚刚被精英队伍成员XLk.Poet_s ...

  8. 4560 NOIP2015 D2T2 子串 code vs

    4560 NOIP2015 D2T2 子串  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 有两个仅包含小写 ...

  9. Android GIS开发系列-- 入门季(4) GraphicsLayer的点击查询要素

    上一讲中我们学会了如何在MapView中添加Graphic要素,那么在百度或高德地图中,当我们点击要素时,会显示出相应的详细信息.在GraphicsLayer中也提供了这样的方法.下面我们来学习在Gr ...

  10. 从尾到头打印链表——剑指Offer

    https://www.nowcoder.net/practice/d0267f7f55b3412ba93bd35cfa8e8035?tpId=13&tqId=11156&tPage= ...