分析
题目乍一看不就是树上背包 O ( n 2 m ) O(n^2m) O(n2m)吗,再加个dfs序优化就可以 O ( n m ) O(nm) O(nm)了,其实不然,因为有些软件先行条件是会形成一个环的,所以还要用tarjan缩点,由于思路比较简单,主要考码题能力,所以就不多说了
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <stack>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=111; stack<int>stac;
struct node{int x,y,next;}e[N<<1],E[N];
int son[N],dfn[N],low[N],num,v[N],w[N],tw[N],mus[N],n,m,k=1,col[N],cnt,c[N],tc[N],ls[N],dp[N][N*5];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void tarjan(int x){
dfn[x]=low[x]=++num;
stac.push(x); v[x]=1;
for (rr int i=ls[x];i;i=E[i].next)
if (!dfn[E[i].y]){
tarjan(E[i].y);
low[x]=min(low[x],low[E[i].y]);
}
else if (v[E[i].y])
low[x]=min(low[x],dfn[E[i].y]);
if (dfn[x]==low[x]){
++cnt; rr int y;
do{
y=stac.top(),stac.pop();
v[y]=0,col[y]=cnt,w[cnt]+=tw[y],c[cnt]+=tc[y];
}while (x!=y);
}
}
inline void add(int x,int y){e[++k]=(node){x,y,ls[x]},ls[x]=k;}
inline void dfs(int x){
dfn[++num]=x,son[x]=1;
for (rr int i=ls[x];~i;i=e[i].next)
mus[e[i].y]=mus[x]+w[x],dfs(e[i].y),son[x]+=son[e[i].y];
}
inline void Mx(int &x,int y){if (x<y) x=y;}
signed main(){
n=iut(); m=iut();
for (rr int i=1;i<=n;++i) tw[i]=iut();
for (rr int i=1;i<=n;++i) tc[i]=iut();
for (rr int i=1;i<=n;++i){
rr int x=iut();
if (x) E[i]=(node){x,i,ls[x]},ls[x]=i;
}
for (rr int i=1;i<=n;++i) if (!dfn[i]) tarjan(i);
memset(ls,-1,sizeof(ls)); memset(dfn,0,sizeof(dfn));
for (rr int i=1;i<=n;++i)
if (E[i].x&&col[E[i].x]!=col[E[i].y])
v[col[E[i].y]]=1,add(col[E[i].x],col[E[i].y]);
for (rr int i=1;i<=cnt;++i) if (!v[i]) add(0,i); num=0;
dfs(0);
for (rr int i=1;i<=num;++i){
for (rr int j=mus[dfn[i]];j<=m-w[dfn[i]];++j)
Mx(dp[i+1][j+w[dfn[i]]],dp[i][j]+c[dfn[i]]);
for (rr int j=mus[dfn[i]];j<=m;++j)
Mx(dp[i+son[dfn[i]]][j],dp[i][j]);
}
return !printf("%d\n",dp[num+1][m]);
}