E80 树上背包 P3354 [IOI2005] Riv 河流
视频链接:E80 树上背包 P3354 [IOI2005] Riv 河流_哔哩哔哩_bilibili
P3354 [IOI2005] Riv 河流 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
// 树上背包 O(n*n*m*m) #include <iostream> #include <cstring> #include <algorithm> #include <vector> #define N 105 using namespace std; int read(){ int d=0;char ch=getchar(); while(!isdigit(ch))ch=getchar(); while(isdigit(ch)){d=d*10+ch-48;ch=getchar();} return d; } vector<int> e[N],stk; int n,m,w[N],a[N],d[N]; int f[N][N][N],g[N][N][N]; void dfs(int u){ stk.push_back(u); for(int v:e[u]){ d[v]=d[u]+a[v]; dfs(v); for(int i:stk){ for(int j=m;j>=0;--j){ f[u][i][j]+=f[v][i][0]; g[u][i][j]+=f[v][u][0]; for(int k=0;k<=j;++k){ f[u][i][j]=min(f[u][i][j],f[u][i][j-k]+f[v][i][k]); g[u][i][j]=min(g[u][i][j],g[u][i][j-k]+f[v][u][k]); } } } } for(int i:stk){ for(int j=m;j>=1;--j) f[u][i][j]=min(f[u][i][j]+w[u]*(d[u]-d[i]),g[u][i][j-1]); f[u][i][0]+=w[u]*(d[u]-d[i]); } stk.pop_back(); } int main(){ n=read(),m=read(); //村庄数,伐木场 for(int i=1,x;i<=n;++i){ w[i]=read(),x=read(),a[i]=read(); e[x].push_back(i); } dfs(0); printf("%d",f[0][0][m]); }