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

【BZOJ2427】[HAOI2010]软件安装

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

5

题解:n个点n条边,所以依赖关系一定会出现环,环中的要么都取要么都不取,那么Tarjan缩环将环变成一个物品即可。然后原图就变成了森林,新建0号点将所有树根连起来然后跑树形背包即可。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int n,m,tot,sum,top,cnt,ans;
int w[110],v[110],d[110],dep[110],low[110],ins[110],sta[110],bel[110],W[110],V[110],D[110];
int to[110],next[110],head[110],f[110][510],vis[110];
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
void tarjan(int x)
{
	dep[x]=low[x]=++tot;
	ins[x]=1,sta[++top]=x;
	if(d[x])
	{
		if(!dep[d[x]])	tarjan(d[x]),low[x]=min(low[x],low[d[x]]);
		else	if(ins[d[x]])	low[x]=min(low[x],dep[d[x]]);
	}
	if(dep[x]==low[x])
	{
		int t;
		sum++;
		do
		{
			t=sta[top--],bel[t]=sum,W[sum]+=w[t],V[sum]+=v[t],ins[t]=0;
		}while(t!=x);
	}
}
void add(int a,int b)
{
	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x)
{
	int i,j,k;
	for(i=0;i<W[x];i++)	f[x][i]=-1<<29;
	f[x][W[x]]=V[x];
	for(i=head[x];i!=-1;i=next[i])
	{
		dfs(to[i]);
		for(j=m;j>=W[x]+W[to[i]];j--)	for(k=W[to[i]];k<=j-W[x];k++)
			f[x][j]=max(f[x][j],f[x][j-k]+f[to[i]][k]);
	}
}
int main()
{
	n=rd(),m=rd();
	int i;
	for(i=1;i<=n;i++)	w[i]=rd();
	for(i=1;i<=n;i++)	v[i]=rd();
	for(i=1;i<=n;i++)	d[i]=rd();
	for(i=1;i<=n;i++)	if(!dep[i])	tarjan(i);
	memset(head,-1,sizeof(head));
	for(i=1;i<=n;i++)	if(bel[d[i]]!=bel[i])	vis[bel[i]]=1,add(bel[d[i]],bel[i]);
	for(i=1;i<=sum;i++)	if(!vis[i])	add(0,i);
	dfs(0);
	for(i=0;i<=m;i++)	ans=max(ans,f[0][i]);
	printf("%d",ans);
	return 0;
}
时间: 2024-10-27 10:15:38

【BZOJ2427】[HAOI2010]软件安装 Tarjan+树形背包的相关文章

【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(包

HAOI2010软件安装(树形背包)

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

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.现在请你设计出

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

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

[HAOI2010][BZOJ2427] 软件安装|tarjan|树型dp

2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 463  Solved: 194[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. 我们现在知道了软件之间的依赖关

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.现在请你设计出一种