原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1775
带依赖关系的背包。为了防止泛化物品之间的并,对于一个泛化物品,强制取那个子树的物品,传给它的子树。(具体表现是传给它的时候就减去它的体积,计算答案时强行加上权值)。
对于当前点有fi,对于它的一棵子树s,先将fi传给fs,并且强制减去体积,计算完fs时,fs已经包含fi,这时候将fi与fs以O(c)复杂度并起来,其实就是将s不取和取的情况取个最优。
type
edge=record
y,next:longint;
end;
var
map:array[0..1000] of edge;
f:array[1..3,0..100050] of longint;
w,v,first:array[0..1000] of longint;
n,c,i,cnt,now,k,s:longint;
ans:int64;
procedure ins(x,y:longint);
begin
inc(s);map[s].y:=y;
map[s].next:=first[x];first[x]:=s;
end;
function max(a,b:longint):longint;
begin if (a>b) then exit(a) else exit(b); end;
procedure deal(dep,now,c:longint);
var
t,y,k:longint;
begin
t:=first[now];
while (t>0) do
begin
y:=map[t].y;
for k:=0 to c do
f[dep+1][k]:=f[dep][k];
deal(dep+1,y,c-w[y]);
for k:=w[y] to c do
f[dep][k]:=max(f[dep][k],f[dep+1][k-w[y]]+v[y]);
t:=map[t].next;
end;
end;
begin
//assign(input,'sad.in');reset(input);
//assign(output,'sad.out');rewrite(output);
read(n,c);
cnt:=0;
w[0]:=0;v[0]:=0;
while (n>0) do
begin
inc(cnt);dec(n);
now:=cnt;
ins(0,now);
read(w[now]);
v[now]:=0;
read(k);
while (k>0) do
begin
inc(cnt);dec(k);
ins(now,cnt);
read(w[cnt],v[cnt]);
end;
end;
deal(1,0,c);
for i:=0 to c do
ans:=max(ans,f[1][i]);
writeln(ans);
//close(input);close(output);
end.