设f[i][j][k]表示i上游最近的一个伐木场为j且在i所在的子树里共建了k个伐木场(不包含在i的)的最小运费和
设v为u的儿子,dist[u]为u到0号点的距离。
则当i>=j时 f[u][last][i]=max{f[u][last][i-j]+dist[v][last][j]+w[v]*(dist[v]-dist[last])} 即在v不放伐木场
当i>j时 f[u][last][i]=max{f[u][last][i-j-1]+f[v][v][j]} 即在v放伐木场
code:
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #define maxn 105 #define inf 1061109567 using namespace std; char ch; int n,k,a,b,c,tot,w[maxn],now[maxn],son[maxn],pre[maxn],val[maxn]; int dist[maxn],f[maxn][maxn][maxn],tmp[maxn][maxn][maxn]; bool ok,bo[maxn][maxn]; void read(int &x){ for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); if (ok) x=-x; } void put(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;} int turn(int x){if (x==inf) return 0;return x;} void dfs(int u,int last){ if (bo[u][last]) return; bo[u][last]=1; for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]){ dist[v]=dist[u]+val[p]; dfs(v,last),dfs(v,v); for (int i=0;i<=k;i++){ f[u][last][i]=inf; for (int j=0;j<=i;j++){ if (i>j) f[u][last][i]=min(f[u][last][i],tmp[u][last][i-j-1]+f[v][v][j]); f[u][last][i]=min(f[u][last][i],tmp[u][last][i-j]+f[v][last][j]+w[v]*(dist[v]-dist[last])); } } memcpy(tmp[u][last],f[u][last],sizeof(tmp[u][last])); } } int main(){ read(n),read(k); for (int i=1;i<=n;i++) read(w[i]),read(b),read(c),put(b,i,c); dfs(0,0); printf("%d ",f[0][0][k]); return 0; }