就是一个普通的树形dp,看错了题目的输入一直wa。
// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3010;
vector<int> G[maxn];
int dp[maxn][maxn];
int vis[maxn][maxn];
int val[maxn];
struct Edge {
int to,cost;
Edge(int _to,int _cost):to(_to),cost(_cost){};
};
vector<Edge> edges;
void addedge(int fo,int to,int cost)
{
Edge e(to,cost),e1(fo,cost);
edges.push_back(e);
G[fo].push_back(edges.size()-1);
edges.push_back(e1);
G[to].push_back(edges.size()-1);
}
int n,m;
int DP(int u,int fa)
{
int len = G[u].size();
dp[u][0]=0;
vis[u][0] = 1;
if(len==1)
{
dp[u][1]=val[u];
vis[u][1]=1;
return 1;
}
int sum = 0;
for (int i=0;i<len;i++) {
Edge e = edges[G[u][i]];
int v=e.to;
if(e.to==fa) continue;
int t = DP(v,u);
sum+=t;
for (int j=sum;j>=1;j--) {
for (int h=1;h<=j;h++) {
if(j>=h&&vis[v][h]&&vis[u][j-h]) {
if(vis[u][j])
dp[u][j] =max(dp[u][j],dp[u][j-h]+dp[v][h]-e.cost);
else {
dp[u][j] =dp[u][j-h]+dp[v][h]-e.cost;
vis[u][j] = 1;
}
}
}
}
}
return sum;
}
int main() {
//freopen("in.txt","r",stdin);
cin>>n>>m;
memset(vis,0,sizeof(vis));
for (int i=1;i<=n-m;i++){
int k;
cin>>k;
for (int j=1;j<=k;j++) {
int to,c;
cin>>to>>c;
addedge(i,to,c);
}
}
for (int i=n-m+1;i<=n;i++) {
int tep;
cin>>tep;
val[i] = tep;
//cin>>val[i];
}
int al = DP(1,0);
for (int i=al;i>=0;i--)
{
if(dp[1][i]>=0) {
al=i;break;
}
}
cout<<al<<endl;
}