1 条题解

  • 0
    @ 2025-11-12 12:59:13

    E80 树上背包 P3354 [IOI2005] Riv 河流

    // 树上背包 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]);
    }
    
    • 1

    信息

    ID
    3468
    时间
    1000ms
    内存
    128MiB
    难度
    10
    标签
    递交数
    4
    已通过
    3
    上传者