題目描述
幾乎整個Byteland王國都被森林和河流所覆蓋。小點的河匯聚到一起,形成了稍大點的河。就這樣,所有的河水都匯聚並流進了一條大河,最後這條大河流進了大海。這條大河的入海口處有一個村莊——名叫Bytetown。
在Byteland國,有n個伐木的村莊,這些村莊都座落在河邊。目前在Bytetown,有一個巨大的伐木場,它處理着全國砍下的所有木料。木料被砍下後,順着河流而被運到Bytetown的伐木場。Byteland的國王決定,爲了減少運輸木料的費用,再額外地建造k個伐木場。這k個伐木場將被建在其他村莊裏。這些伐木場建造後,木料就不用都被送到Bytetown了,它們可以在運輸過程中第一個碰到的新伐木場被處理。顯然,如果伐木場座落的那個村子就不用再付運送木料的費用了。它們可以直接被本村的伐木場處理。
注:所有的河流都不會分叉,形成一棵樹,根結點是Bytetown。
國王的大臣計算出了每個村子每年要產多少木料,你的任務是決定在哪些村子建設伐木場能獲得最小的運費。其中運費的計算方法爲:每一噸木料每千米1分錢。
輸入輸出格式
輸入格式:
第一行包括兩個數 n(2≤n≤100),k(1≤k≤50,且 k≤n)。n爲村莊數,k爲要建的伐木場的數目。除了Bytetown外,每個村子依次被命名爲1,2,3……n,Bytetown被命名爲0。
接下來n行,每行3個整數:
wi——每年i村子產的木料的塊數(0≤wi≤10000)
vi——離i村子下游最近的村子(即i村子的父結點)(0≤vi≤n)
di——vi到i的距離(千米)。(1≤di≤10000)
保證每年所有的木料流到bytetown的運費不超過2,000,000,000分
50%的數據中n不超過20。
輸出格式:
輸出最小花費,單位爲分。
輸入輸出樣例
輸入樣例#1:
4 2
1 0 1
1 1 10
10 2 5
1 2 3
輸出樣例#1:
4
樹上分組揹包+約定祖先
#include<iostream>
#include<cstdio>
using namespace std;
inline int rd() {
int ret=0,f=1;
char c;
while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret*f;
}
const int MAXN=155;
struct Edge {
int next,to,w;
} e[MAXN];
int ecnt,head[MAXN];
inline void add(int x,int y,int w) {
e[++ecnt].next = head[x];
e[ecnt].to = y;
e[ecnt].w = w;
head[x] = ecnt;
}
int n,k;
int val[MAXN];
int f[MAXN][MAXN][MAXN];
int g[MAXN][MAXN][MAXN];
int stack[MAXN],top;
int dep[MAXN];
void dfs(int x) {
stack[++top]=x;
for(int i=head[x]; i; i=e[i].next) {
int v=e[i].to;
dep[v]=dep[x]+e[i].w;
dfs(v);
for(int fa=1; fa<=top; fa++) {
for(int j=k; j>=0; j--) {
f[x][j][stack[fa]]+=f[v][0][stack[fa]];
g[x][j][stack[fa]]+=f[v][0][x];
for(int u=0; u<=j; u++) {//
f[x][j][stack[fa]]=min(f[x][j][stack[fa]],f[x][j-u][stack[fa]]+f[v][u][stack[fa]]);
g[x][j][stack[fa]]=min(g[x][j][stack[fa]],g[x][j-u][stack[fa]]+f[v][u][x]);
}
}
}
}
for(int fa=1; fa<=top; fa++) {
for(int j=0; j<=k; j++) {
if(j>=1) f[x][j][stack[fa]]=min(f[x][j][stack[fa]]+val[x]*(dep[x]-dep[stack[fa]]),g[x][j-1][stack[fa]]);
else f[x][j][stack[fa]]+=val[x]*(dep[x]-dep[stack[fa]]);
}
}
top--;
}
int main() {
n=rd();
k=rd();
for(int i=1; i<=n; i++) {
int y,w;
val[i]=rd();
y=rd();
w=rd();
add(y,i,w);
}
dfs(0);
cout<<f[0][k][0];
return 0;
}