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

题意:

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

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

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

分析:
有环。

考虑一个环内的贡献

要么都取要么都不取

缩个点跑树形背包就可以了

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 350
int head[N],to[N<<1],nxt[N<<1],cnt,n;
int m,f[N][600],cost[N],val[N],c[N],v[N],in[N];
int st[N],top,ins[N],bl[N],scc,tot,vis[N];
int dfn[N],low[N],from[N];
inline void add(int u,int v){
    to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;from[cnt]=u;
}
void tarjan(int x){
    st[top++]=x;
    ins[x]=1;
    low[x]=dfn[x]=++tot;
    for(int i=head[x];i;i=nxt[i]){
        if(!dfn[to[i]]){
            tarjan(to[i]);
            low[x]=min(low[x],low[to[i]]);
        }else if(ins[to[i]]){
            low[x]=min(low[x],dfn[to[i]]);
        }
    }
    if(low[x]==dfn[x]){
        int t=st[--top];ins[t]=0;
        bl[t]=++scc;
        c[scc]=cost[t];
        v[scc]=val[t];
        while(t^x){
            t=st[--top];ins[t]=0;
            c[scc]+=cost[t];
            v[scc]+=val[t];
            bl[t]=scc;
        }
    }
}
void dfs(int x,int y){
    f[x][c[x]]=v[x];
    vis[x]=1;
    for(int i=head[x];i;i=nxt[i]){
        if(!vis[to[i]]){
            dfs(to[i],x);
            for(int j=m;j>=c[x];j--){
                for(int k=m-j;k>=c[to[i]];k--){
                    f[x][j+k]=max(f[x][j+k],f[x][j]+f[to[i]][k]);
                }
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    int i,j,x,y;
    for(i=1;i<=n;i++)scanf("%d",&cost[i]);
    for(i=1;i<=n;i++)scanf("%d",&val[i]);
    for(i=1;i<=n;i++){
        scanf("%d",&x);
        if(x)
        	add(x,i);
    }
    for(i=1;i<=n;i++)if(!dfn[i])tarjan(i);
    int tmp=cnt;
    memset(head,0,sizeof(head));cnt=0;
    for(i=1;i<=tmp;i++){
        x=from[i],y=to[i];
        if(bl[x]!=bl[y]){
            add(bl[x],bl[y]);
            in[bl[y]]++;
        }
    }
    for(i=1;i<=scc;i++)if(!in[i]){
        add(scc+1,i);
    }
    dfs(scc+1,0);
    int ans=0;
    for(i=0;i<=m;i++)ans=max(ans,f[scc+1][i]);
    printf("%d\n",ans);
}
/*
3 10
5 5 6
2 3 4
0 1 1
*/

原文地址:https://www.cnblogs.com/suika/p/8511857.html

时间: 2024-10-09 22:28:27

BZOJ_2427_[HAOI2010]软件安装_tarjan+树形DP的相关文章

HAOI2010软件安装(树形背包)

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

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

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

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

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

P2515 [HAOI2010]软件安装

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

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

[Bzoj 2427] [HAOI2010] 软件安装 tarjan缩点+树形DP

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

HAOI2010 软件安装 有依赖的背包DP

题目描述 现在我们的手头有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.现在请你设计出一种

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

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