自定义HP背景好评!
analysis
有传递关系,还可能成环?缩点!
缩点后呢?显然是一棵树了
求整棵树分W空间的收益,和子树分Wi空间的收益好像有点关系
子问题相似,边界问题就是叶子结点
emm,树形DP吗?
试一下,好像可以诶!
于是就这样做:
- 缩点
- 树形DP
时间复杂度 O(n3)O(n^3)O(n3)
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,s,e) for(register int i=s;i<=e;++i)
#define anti_loop(i,s,e) for(register int i=s;i>=e;--i)
#define clean(a,n) memset(a,n,sizeof(a))
#define isdegit(a) ((a>='0'&&a<='9'))
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(!isdegit(r)){if(r=='-')neg=-1;r=getchar();}
while(isdegit(r)){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
const int maxn=100+10;
const int maxm=500+10;
int n,m;
int W[maxn],V[maxn],D[maxn];
struct node{
int e;
int nxt;
}edge[maxn<<1];
int head[maxn];
int cnt=0;
inline void addl(int u,int v){
edge[++cnt].e=v;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
int dfn[maxn];
int low[maxn];
int sta[maxn];
int bel[maxn];
int sumW[maxn];
int sumV[maxn];
int col=0;
int nfp=0;
int top=0;
void tarjan(int u){
dfn[u]=low[u]=++nfp;
sta[++top]=u;
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(!bel[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
bel[u]=++col;
sumW[col]+=W[u];
sumV[col]+=V[u];
while(sta[top]!=u){
bel[sta[top]]=col;
sumW[col]+=W[sta[top]];
sumV[col]+=V[sta[top]];
--top;
}
--top;
}
}
struct road{
int xi;
int yi;
}line[maxn];
inline bool cmp(road a,road b){
return ((a.xi==b.xi)?a.yi<b.yi:a.xi<b.xi);
}
int in[maxn];
#define belonging(x) x=bel[x]
inline void reset(){
loop(i,1,cnt){
belonging(line[i].xi);
belonging(line[i].yi);
}
int _m=cnt;
sort(line+1,line+1+_m,cmp);
clean(head,-1);
cnt=0;
loop(i,1,_m){
if(line[i].xi!=line[i].yi&&(line[i].xi!=line[i-1].xi||line[i].yi!=line[i-1].yi)){
addl(line[i].xi,line[i].yi);
++in[line[i].yi];
}
}
}
int f[maxn][maxm];
void dfs(int u){
loop(i,sumW[u],m)
f[u][i]=sumV[u];
for(int i=head[u];i!=-1;i=edge[i].nxt){
int v=edge[i].e;
dfs(v);
anti_loop(j,m-sumW[u],0){
loop(k,0,j){
f[u][j+sumW[u]]=max(f[u][j+sumW[u]],f[u][j+sumW[u]-k]+f[v][k]);
}
}
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif // ONLINE_JUDGE
clean(head,-1);
clean(dfn,0);
clean(low,0);
clean(bel,0);
clean(in,0);
read(n);
read(m);
loop(i,1,n)
read(W[i]);
loop(i,1,n)
read(V[i]);
loop(i,1,n){
read(D[i]);
if(D[i]){
addl(D[i],i);
line[cnt].yi=i;
line[cnt].xi=D[i];
}
}
loop(i,1,n)
if(!dfn[i])
tarjan(i);
reset();
loop(i,1,col){
if(!in[i]){
addl(0,i);
}
}
dfs(0);
printf("%d\n",f[0][m]);
return 0;
}