1 条题解
-
0
把 向 连边。然后就形成了一个外向基环树森林。缩点之后树形 DP,只有选了 才能选 的儿子。
#include<bits/stdc++.h> #define int long long using namespace std; const int N=105; int n,m,c[N],h[N],dfn[N],low[N],times,bel[N],cnt,C[N],H[N],ind[N],ins[N],dp[N][505],vis[N]; vector<int>G[N],g[N]; stack<int>s; void Tarjan(int u) { dfn[u]=low[u]=++times,s.push(u),ins[u]=1; for(auto v:G[u]) if(!dfn[v])Tarjan(v),low[u]=min(low[u],low[v]); else if(ins[v])low[u]=min(low[u],dfn[v]); if(dfn[u]==low[u]) { ++cnt; int v; do { v=s.top(),s.pop(),ins[v]=0; bel[v]=cnt; C[cnt]+=c[v],H[cnt]+=h[v]; } while(u!=v); } } void DP(int u) { for(int i=C[u]; i<=m; i++) dp[u][i]=H[u]; vis[u]=1; for(auto v:g[u]) if(!vis[v]) { DP(v); for(int i=m; i>=C[u]; --i)for(int j=0; j<=i; ++j)if(i-j>=C[u]) dp[u][i]=max(dp[u][i],dp[u][i-j]+dp[v][j]); } } signed main() { std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); cin>>n>>m; for(int i=1; i<=n; ++i)cin>>c[i]; for(int i=1; i<=n; ++i)cin>>h[i]; for(int i=1,f; i<=n; ++i) { cin>>f; if(f)G[f].push_back(i); } for(int i=1; i<=n; ++i) if(!dfn[i]) Tarjan(i); for(int u=1; u<=n; ++u) for(auto v:G[u]) if(bel[u]!=bel[v]) g[bel[u]].push_back(bel[v]),++ind[bel[v]]; for(int i=1; i<=cnt; ++i) if(ind[i]==0) g[0].push_back(i); DP(0); cout<<dp[0][m]<<"\n"; return 0; }
信息
- ID
- 409
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 17
- 已通过
- 2
- 上传者