[HAOI2010]软件安装

题目描述

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

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

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

输入输出格式

输入格式:

第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 )

输出格式:

一个整数,代表最大价值

输入输出样例

输入样例#1:

3 10
5 5 6
2 3 4
0 1 1

输出样例#1:

5

首先对于每个i,从i向Di建一条有向边。

在这里我们发现,依赖关系可以形成环。对于一个环,里面的节点要么都选,要么都不选。

所以,这里先Tarjan强连通分量缩点,构成一个新图,这样新图里的每个节点可以看成一个整体考虑

然后就变成裸的树形dp

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 struct Messi
  7 {
  8     int next,to;
  9 }edge[10001],edge2[10001];
 10 int head[10001],num,low[10001],dfn[10001],dfscnt,stack[10001],inStack[10001];
 11 int n,m,scnt,top,sccno[10001];
 12 int ans,num2,head2[10001],w[10001];
 13 int v[10001],V[10001],W[10001],f[501][1001];
 14 bool b[1001];
 15 void add(int u,int v)
 16 {
 17     num++;
 18     edge[num].next=head[u];
 19      edge[num].to=v;
 20      head[u]=num;
 21 }
 22 void add2(int u,int v)
 23 {
 24     num2++;
 25     edge2[num2].next=head2[u];
 26      edge2[num2].to=v;
 27      head2[u]=num2;
 28 }
 29 void dfs(int u)
 30 {int i,j;
 31     low[u]=dfn[u]=++dfscnt;
 32     stack[++top]=u;
 33      inStack[u]=1;
 34      for (i=head[u];i;i=edge[i].next)
 35      {
 36         int v=edge[i].to;
 37          if (dfn[v]==0)
 38          {
 39             dfs(v);
 40             low[u]=min(low[u],low[v]);
 41          }else if (inStack[v]) low[u]=min(low[u],dfn[v]);
 42      }
 43      if (dfn[u]==low[u])
 44      {
 45         ++scnt;
 46         while (top&&stack[top+1]!=u)
 47         {
 48             sccno[stack[top]]=scnt;
 49             inStack[stack[top--]]=0;
 50         }
 51      }
 52 }
 53 void dp(int x)
 54 {int i,j,k;
 55     for (i=head2[x];i;i=edge2[i].next)
 56     {
 57       int v=edge2[i].to;
 58         dp(v);
 59         for (j=m-V[x];j>=0;j--)
 60         {
 61             for (k=0;k<=j;k++)
 62             f[x][j]=max(f[x][j],f[x][k]+f[v][j-k]);
 63         }
 64     }
 65     for (j=m;j>=0;j--)
 66     if (j-V[x]>=0)
 67      f[x][j]=f[x][j-V[x]]+W[x];
 68      else f[x][j]=0;
 69 }
 70 int main()
 71 {int i,x,j;
 72   cin>>n>>m;
 73   for (i=1;i<=n;i++)
 74   scanf("%d",&v[i]);
 75   for (i=1;i<=n;i++)
 76   scanf("%d",&w[i]);
 77   for (i=1;i<=n;i++)
 78   {
 79     scanf("%d",&x);
 80     if (x) add(x,i);
 81   }
 82   for (i=1;i<=n;i++)
 83        if (dfn[i]==0) dfs(i);
 84        for (i=1;i<=n;i++)
 85        {
 86          int u=sccno[i];
 87             W[u]+=w[i];
 88             V[u]+=v[i];
 89           for (j=head[i];j;j=edge[j].next)
 90            {
 91             int v=sccno[edge[j].to];
 92             if (u!=v) b[v]=1,add2(u,v);
 93            }
 94        }
 95    for (i=1;i<=scnt;i++)
 96    {
 97       if (b[i]==0)
 98       add2(scnt+1,i);
 99    }
100    dp(scnt+1);
101    cout<<f[scnt+1][m];
102 }
时间: 2024-10-25 07:49:29

[HAOI2010]软件安装的相关文章

BZOJ2427: [HAOI2010]软件安装

2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1512  Solved: 584[Submit][Status][Discuss] Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j

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

[BZOJ2427][HAOI2010]软件安装 Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0.我们现在知道

P2515 [HAOI2010]软件安装

P2515 [HAOI2010]软件安装 题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关

HAOI2010软件安装(树形背包)

HAOI2010软件安装(树形背包) 题意 有n个物品,每个物品最多会依赖一个物品,但一个物品可以依赖于一个不独立(依赖于其它物品)的物品,且可能有多个物品依赖一个物品,并且依赖关系可能形成一个环.现给你V的资金,问如何分配资金,可以使你的得到的总价值最大,请求出这个总价值. 解法 我以前写过对于普通依赖性背包的博客:noip2006金明的预算方案如果对依赖性背包不是很熟悉的同学可以先看一下这道题. 由于这道题的依赖关系可能形成环,所以我们先用tarjan缩一下点,然后依赖关系图就变成了一个森林

洛谷 P2515 [HAOI2010]软件安装

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出一种

洛谷—— P2515 [HAOI2010]软件安装

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出一种

bzoj 2427: [HAOI2010]软件安装

Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在

cogs 444. [HAOI2010]软件安装

★★☆   输入文件:install.in   输出文件:install.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述]现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一 些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大).但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的 是,一个软件最

BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP

题意: 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出一种方