软件安装
Description
现在我们的手头有
N
个软件,对于一个软件
我们希望从中选择一些软件安装到一台磁盘容量为
M
的计算机上,使得这些软件的价值尽可能大(即
但是现在有个问题:软件之间存在依赖关系,即软件
i
只有在安装了软件
幸运的是,一个软件最多依赖另外一个软件。
如果一个软件不能正常工作,那么它能够发挥的作用为
0
。
我们现在知道了软件之间的依赖关系:软件
现在请你设计出一种方案,安装价值尽量大的软件。
一个软件只能被安装一次,如果一个软件没有依赖则
Di=0
,这时只要这个软件安装了,它就能正常工作。
Input
第
1
行:
第
2
行:
第
3
行:
第
4
行:
Output
一个整数,代表最大价值。
Sample Input
3 10
5 5 6
2 3 4
0 1 1
Sample Output
5
Solution
首先,可能有环。
所以我们要先缩点。我用的是
Tarjan
求强连通分量。
然后就是一个经典的树形依赖背包问题,
O(nm)
即可解决。
推荐资料:徐持衡的论文《浅谈几类背包问题》。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define Min(x,y) ((x)<(y)?(x):(y))
#define Max(x,y) ((x)>(y)?(x):(y))
using namespace std;
int n,m,cnt,top,tot,tott,front,cnt2;
int score[50010],w[50010],w1[50100],v1[50010],f[5100][2010],dfn[50100],stack[05010];
int head[10010],nxt[10000],data[10000],belong[10000],pre[10000],queue[10000];
int head1[10010],nxt1[10010],data1[10010];
bool vissss[50010],vis[50010],in_stack[50010],can[1000][1000],pres[1000];
void add(int x,int y){
nxt[cnt]=head[x];data[cnt]=y;head[x]=cnt++;
}
void add2(int x,int y){
nxt1[cnt2]=head1[x];data1[cnt2]=y;head1[x]=cnt2++;
}
void dfs(int s,int v){
if(v<=0)return;
for(int i=head1[s];i!=-1;i=nxt1[i]){
int d=data1[i];
for(int j=0;j<=v-w1[d];j++)f[d][j]=f[s][j]+v1[d];
dfs(d,v-w1[d]);
for(int j=w1[d];j<=v;j++){
if(f[s][j]<f[d][j-w1[d]])
f[s][j]=f[d][j-w1[d]];
}
}
}
void Tarjan(int x){
pre[x]=dfn[x]=++tot;
in_stack[x]=true;
stack[++top]=x;
for(int i=head[x];i!=-1;i=nxt[i]){
if(!dfn[data[i]]){
Tarjan(data[i]);
pre[x]=Min(pre[x],pre[data[i]]);
}
else if(in_stack[data[i]])pre[x]=Min(pre[x],dfn[data[i]]);
}
if(dfn[x]==pre[x]){
tott++;
belong[x]=tott;
int j;
do{
j=stack[top--];
in_stack[j]=false;
belong[j]=tott;
w1[tott]+=w[j];
v1[tott]+=score[j];
}while(j!=x);
}
}
void bfs(int ss){
queue[++front]=ss;
while(front){
int now=queue[front--];
for(int i=head[now];i!=-1;i=nxt[i]){
if(belong[now]!=belong[data[i]]&&!can[belong[now]][belong[data[i]]]){
can[belong[now]][belong[data[i]]]=can[belong[data[i]]][belong[now]]=true;
add2(belong[now],belong[data[i]]);
pres[belong[data[i]]]=true;
}
if(!vis[data[i]]){
queue[++front]=data[i];
vis[data[i]]=false;
}
}
}
}
inline void in(int &y){
y=0;
char x=getchar();
while(x<'0'||x>'9')x=getchar();
while(x>='0'&&x<='9'){y=y*10+x-'0';x=getchar();}
}
int main(){
memset(head,-1,sizeof head);
memset(head1,-1,sizeof head1);
in(n);in(m);
for(int i=1;i<=n;i++)in(w[i]);
for(int i=1;i<=n;i++)in(score[i]);
for(int i=1;i<=n;i++){
int x;
in(x);
add(x,i);
}
for(int i=0;i<=n;i++)if(!belong[i])Tarjan(i);
for(int i=1;i<=n;i++)if(!vis[i]){
vis[i]=true;
bfs(i);
}
for(int i=1;i<=tott;i++)if(!pres[i]&&i!=belong[0]){
add2(belong[0],i);
}
dfs(belong[0],m);
printf("%d\n",f[belong[0]][m]);
return 0;
}