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]);
}

 

posted @ 2024-11-08 16:35  董晓  阅读(50)  评论(0编辑  收藏  举报