/* 依赖背包 dp[i][j]表示i结点为根的树选择j个用户时的最大剩余费用 即背包容量是j,价值是最大费用 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define maxn 3050 struct Edge{int to,nxt,w;}edge[maxn<<1]; int n,m,k,head[maxn],tot,num[maxn],dp[maxn][maxn]; void init(){ memset(head,-1,sizeof head); tot=0; } void addedge(int u,int v,int w){ edge[tot].to=v;edge[tot].w=w;edge[tot].nxt=head[u]; head[u]=tot++; } void dfs(int u,int pre){ for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==pre)continue; dfs(v,u); num[u]+=num[v]; } for(int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(v==pre)continue; for(int j=num[u];j>=0;j--) for(int t=0;t<=num[v];t++) dp[u][j]=max(dp[u][j],dp[u][j-t]+dp[v][t]-edge[i].w); } //printf("%d %d\n",u,dp[u][1]); } int main(){ int v,w; while(cin>>n>>m){ init(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)dp[i][j]=-0x3f3f3f3f; for(int i=1;i<=n-m;i++){// cin>>k; while(k--){ cin>>v>>w; addedge(i,v,w); addedge(v,i,w); num[i]=0; } } for(int i=n-m+1;i<=n;i++) num[i]=1,cin>>dp[i][1]; dfs(1,0); for(int j=m;j>=0;j--) if(dp[1][j]>=0){ printf("%d\n",j); break; } } }