左孩子有兄弟表示树,想明白了也不是很难.。
每DP完成一个孩子节点,就用这个孩子节点更新父亲的信息。
#include<iostream>
#include<cstring>
#include<cstdio>
#define INF 99999999
#define maxn 3010
using namespace std;
struct node
{
int v,w; // v is u's first child
int next;
node()
{
v=w=-1;
next=-1;
}
}p[maxn];
int temp[maxn];
int num[maxn];
int dp[maxn][maxn];
int n,m;
void add_edge(int x,int y,int w)
{
p[y].next=p[x].v;
p[x].v=y;p[y].w=w;
}
void init()
{
int c,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dp[i][j]=-INF;
for(int i=1;i<=n-m;i++)
{
scanf("%d",&c);
for(int j=0;j<c;j++)
{
scanf("%d%d",&x,&y);
add_edge(i,x,y);
}
}
for(int i=n-m+1;i<=n;i++)
{
scanf("%d",&x);
dp[i][1]=x;
num[i]=1;
}
}
void DP_process(int u)
{
for(int v=p[u].v;v!=-1;v=p[v].next)
{
DP_process(v);
for(int i=0;i<=num[u];i++)
temp[i]=dp[u][i];
for(int i=0;i<=num[u];i++)
{
for(int j=1;j<=num[v];j++)
{
dp[u][i+j]=max(dp[u][i+j],temp[i]+dp[v][j]-p[v].w);
}
}
num[u]+=num[v];
}
}
void solve()
{
bool ok=false;
DP_process(1);
for(int i=m;i>=0;i--)
if(dp[1][i]>=0)
{
ok=true;
printf("%d\n",i);
break;
}
}
int main()
{
freopen("1155.txt","r",stdin);
init();
solve();
return 0;
}