这么水的题我一遍没A,而且前两次提交都只有十分。气死我了。本来我的博客拒收水题来着。
Tarjan缩点之后跑树形DP即可。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<cstdlib> #include<queue> #define maxn 300 #define maxm 600 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int w[maxn]; int c[maxn]; int dfn[maxn],ID; int low[maxn]; int stack[maxn],top; int col[maxn],cnt; int colw[maxn],colc[maxn]; bool vis[maxn]; int f[maxn][maxm]; int indl[maxn]; int n,m; struct Pic{ struct Edge{ int next,to; }edge[maxn*2]; int head[maxn],num; Pic(){num=0;memset(head,0,sizeof(head)); } inline void add(int from,int to){ edge[++num]=(Edge){head[from],to}; head[from]=num; } void tarjan(int x){ vis[x]=1;stack[++top]=x; dfn[x]=low[x]=++ID; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; if(!dfn[to]){ tarjan(to); low[x]=min(low[x],low[to]); } else if(vis[to]) low[x]=min(low[x],dfn[to]); } if(dfn[x]==low[x]){ col[x]=++cnt; vis[x]=0; colw[cnt]=w[x]; colc[cnt]=c[x]; while(stack[top]!=x){ vis[stack[top]]=0; col[stack[top]]=cnt; colw[cnt]+=w[stack[top]]; colc[cnt]+=c[stack[top]]; top--; } top--; } } void dfs(int x){ for(int i=m;i>=colw[x];--i) f[x][i]=colc[x]; for(int i=head[x];i;i=edge[i].next){ int to=edge[i].to; dfs(to); for(int j=m;j>=0;--j) for(int k=0;j-k>=colw[x];++k) f[x][j]=max(f[x][j],f[x][j-k]+f[to][k]); } return; } }Old,New; int main(){ n=read();m=read(); for(int i=1;i<=n;++i) w[i]=read(); for(int i=1;i<=n;++i) c[i]=read(); for(int i=1;i<=n;++i){ int x=read(); if(x) Old.add(x,i); } for(int i=1;i<=n;++i) if(!dfn[i]) Old.tarjan(i); for(int i=1;i<=n;++i) for(int j=Old.head[i];j;j=Old.edge[j].next){ int to=Old.edge[j].to; if(col[i]==col[to]) continue; New.add(col[i],col[to]); indl[col[to]]++; } for(int i=1;i<=cnt;++i) if(!indl[i]) New.add(0,i); New.dfs(0); printf("%d",f[0][m]); return 0; }