[HAOI2010]软件安装
题目:洛谷P2515、BZOJ2427、codevs1866。
题目大意:有n个物品,每个物品有重量和价值,且只能选一次。每个物品可能有一个依赖物品,选了该物品必须先选择它的依赖物品(可能会有环)。给出背包的容量,求可以装物品的最大价值。
解题思路:首先强连通分量缩点,然后树形dp求01背包即可。
C++ Code:
#include<bits/stdc++.h>
int n,m,fa[105],w[105],v[105],dfn[105],low[105],idx=0,ys[105],ltfl=0,dad[105];
std::vector<int>a[105];
int f[105][505],W[105],V[105],ans=0,cnt=0,head[105];
bool instack[105];
std::stack<int>s;
inline int debian(){
int c=getchar();
for(;!isdigit(c);c=getchar());
int d=0;
for(;isdigit(c);c=getchar())
d=(d<<3)+(d<<1)+(c^'0');
return d;
}
struct edge{
int to,nxt;
}e[66667];
void tarjan(int now){
dfn[now]=low[now]=++idx;
s.push(now);
instack[now]=true;
if(fa[now]){
if(dfn[fa[now]]){
if(instack[fa[now]]&&low[now]>dfn[fa[now]])
low[now]=dfn[fa[now]];
}else{
tarjan(fa[now]);
if(low[now]>low[fa[now]])low[now]=low[fa[now]];
}
}
if(low[now]==dfn[now]){
++ltfl;
int p;
do{
p=s.top();
s.pop();
instack[p]=false;
a[ltfl].push_back(p);
ys[p]=ltfl;
W[ltfl]+=w[p];
V[ltfl]+=v[p];
}while(p!=now);
}
}
void dp(int now){
//fprintf(stderr,"233 %d 233\n",now);
for(int i=W[now];i<=m;++i)
f[now][i]=V[now];
for(int i=head[now];i;i=e[i].nxt){
dp(e[i].to);
for(int j=m;j>=W[now];--j){
for(int k=0;k<=m;++k){
if(k+j>m)break;
if(f[now][j+k]<f[now][j]+f[e[i].to][k])f[now][j+k]=f[now][j]+f[e[i].to][k];
}
}
}
}
int main(){
n=debian(),m=debian();
memset(fa,-1,sizeof fa);
for(int i=1;i<=n;++i)w[i]=debian();
for(int i=1;i<=n;++i)v[i]=debian();
for(int i=1;i<=n;++i)fa[i]=debian();
memset(dfn,0,sizeof dfn);
memset(W,0,sizeof W);
memset(V,0,sizeof V);
for(int i=1;i<=n;++i)
if(!dfn[i])tarjan(i);
//fprintf(stderr,"%d\n",ltfl);
for(int i=1;i<=n;++i){
if(fa[i]==0||a[ys[i]].size()>1)dad[ys[i]]=0;else
dad[ys[i]]=ys[fa[i]];
}
memset(f,0,sizeof f);
memset(head,0,sizeof head);
//for(int i=1;i<=ltfl;++i)fprintf(stderr,"%d: %d %d %d\n",i,dad[i],W[i],V[i]);
for(int i=1;i<=ltfl;++i){
e[++cnt]=(edge){i,head[dad[i]]};
head[dad[i]]=cnt;
}
dp(0);
for(int i=0;i<=m;++i)
if(f[0][i]>ans)ans=f[0][i];
//for(int i=0;i<=ltfl;++i,putchar('\n'))
//for(int j=0;j<=m;++j)printf("%d ",f[i][j]);
return!printf("%d\n",ans);
}

浙公网安备 33010602011771号