思路:去掉强连通分量,再树形01背包
#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,w[110],v[110],d[110],dfn[110],low[110],scc[110],sum[110],ans,f[110][510];
int hd[110],ne[510],to[510],ll[510],vl[510],tot;
stack<int> s;
vector<int> g[110],len[110],val[110];
void add(int x,int y,int w,int v){
tot+=1;
ne[tot]=hd[x];
hd[x]=tot;
to[tot]=y;
ll[tot]=w;
vl[tot]=v;
}
void dfs(int x){
cnt+=1;
dfn[x]=cnt;
low[x]=cnt;
s.push(x);
for(int i=hd[x];i>=1;i=ne[i])
{
if(scc[to[i]]!=0)continue;
if(dfn[to[i]]==0)
{
dfs(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x])
{
ans+=1;
while(s.top()!=x)
{
sum[ans]+=1;
scc[s.top()]=ans;
s.pop();
}
sum[ans]+=1;
scc[x]=ans;
s.pop();
}
}
void dfs_ans(int x){
int l=g[x].size();
for(int i=0;i<=l-1;i++)
{
dfs_ans(g[x][i]);
for(int j=m;j>=len[x][i];j--)
f[x][j]=max(f[x][j],f[g[x][i]][j-len[x][i]]+val[x][i]);
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n;i++)
scanf("%d",&v[i]);
for(int i=1;i<=n;i++)
scanf("%d",&d[i]);
for(int i=1;i<=n;i++)
add(d[i],i,w[i],v[i]);
for(int i=1;i<=n;i++)
if(dfn[i]==0)dfs(i);
sum[0]=1;
for(int i=0;i<=n;i++)
{
for(int j=hd[i];j>=1;j=ne[j])
{
if(scc[i]!=scc[to[j]]&&sum[scc[i]]==1&&sum[scc[to[j]]]==1)
{
g[scc[i]].push_back(scc[to[j]]);
len[scc[i]].push_back(ll[to[j]]);
val[scc[i]].push_back(vl[to[j]]);
}
}
}
dfs_ans(0);
printf("%d",f[0][m]);
return 0;
}