貪喫的九頭龍
題目描述
傳說中的九頭龍是一種特別貪喫的動物。
雖然名字叫“九頭龍”,但這只是說它出生的時候有九個
頭,而在成長的過程中,它有時會長出很多的新頭,頭的總數會遠大於九,當然也會有舊頭因衰老而自己脫落。
有一天,有
可是必須照顧到每個頭,因此它需要把
這
果子由
對於每段樹枝,如果它所連接的兩個果子需要由不同的頭來喫掉,那麼兩個頭會共同把樹枝弄斷而把果子分開;如果這兩個果子是由同一個頭來喫掉,那麼這個頭會懶得把它弄斷而直接把果子連同樹枝一起喫掉。
當然,喫樹枝並不是很舒服的,因此每段樹枝都有一個喫下去的“難受值”,而九頭龍的難受值就是所有頭喫掉的樹枝的“難受值”之和。
九頭龍希望它的“難受值”儘量小,你能幫它算算嗎?
例如 圖1 所示的例子中,果樹包含
即
圖一描述了果樹的形態,圖二描述了最優策略。
輸入格式
第
第
輸出格式
一行,包含一個整數,表示在滿足“大頭”的要求的前提下,九頭龍的難受值的最小值。
如果無法滿足要求,輸出 -1 。
樣例輸入
8 2 4
1 2 20
1 3 4
1 4 13
2 5 10
2 6 12
3 7 15
3 8 5
樣例輸出
4
數據範圍
Solution
首先,判斷無解的條件:
狀態表示:
用
狀態轉移方程就很簡單了。
Code
#include <iostream>
#include <cstdio>
#include <cstring>
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
int n,m,k,cnt,cnts,f[900][900][4],fa[900];
int nxt[900],data[900],flow[900],head[900];
int nxts[900],datas[900],flows[900],heads[900];
int child[900][900],ans;
void add(int x,int y,int z){
nxt[cnt]=head[x];data[cnt]=y;flow[cnt]=z;head[x]=cnt++;
}
void add1(int x,int y,int z){
nxts[cnts]=heads[x];datas[cnts]=y;flows[cnts]=z;heads[x]=cnts++;
nxts[cnts]=heads[y];datas[cnts]=x;flows[cnts]=z;heads[y]=cnts++;
}
void dfs(int now,int pre){
int first=-1;
for(int i=heads[now];i!=-1;i=nxts[i])if(datas[i]!=pre){
child[now][datas[i]]=flows[i];
fa[datas[i]]=now;
if(first==-1){
add(now,datas[i],flows[i]);
first=datas[i];
}
else{
add(first,datas[i],flows[i]);
first=datas[i];
}
dfs(datas[i],now);
}
}
int dp(int now,int need,bool turn){
if(f[now][need][turn]!=-1)return f[now][need][turn];
int tmp1=0,tmp2=0,p=-1,br=-1;
if(turn==1)tmp1=child[fa[now]][now];
else if(m==2)tmp2=child[fa[now]][now];
for(int j=head[now];j!=-1;j=nxt[j])if(child[now][data[j]]!=-1){
p=data[j];
break;
}
for(int j=head[now];j!=-1;j=nxt[j])if(child[fa[now]][data[j]]!=-1){
br=data[j];
break;
}
if(need==0){
if(p==-1&&br!=-1){
tmp2+=dp(br,need,turn);
}
else if(p!=-1&&br==-1){
tmp2+=dp(p,need,0);
}
else if(p!=-1&&br!=-1){
int zz=0x3f3f3f3f;
zz=Min(zz,dp(br,0,turn)+dp(p,0,0));tmp2+=zz;
}
else return f[now][need][turn]=Min(0x3f3f3f3f,tmp2);
return f[now][need][turn]=Min(0x3f3f3f3f,tmp2);
}
if(p==-1&&br!=-1){
tmp1+=dp(br,need-1,turn);
tmp2+=dp(br,need,turn);
}
else if(p!=-1&&br==-1){
tmp1+=dp(p,need-1,1);
tmp2+=dp(p,need,0);
}
else if(p!=-1&&br!=-1){
int zz=0x3f3f3f3f;
for(int i=0;i<need;i++)zz=Min(zz,dp(br,need-i-1,turn)+dp(p,i,1));tmp1+=zz;
zz=0x3f3f3f3f;
for(int i=0;i<=need;i++)zz=Min(zz,dp(br,need-i,turn)+dp(p,i,0));tmp2+=zz;
}
else{
if(need==1)return f[now][need][turn]=Min(0x3f3f3f3f,tmp1);
else if(!need)return f[now][need][turn]=Min(0x3f3f3f3f,tmp2);
else return f[now][need][turn]=0x3f3f3f3f;
}
return f[now][need][turn]=Min(0x3f3f3f3f,Min(tmp2,tmp1));
}
int main(){
freopen("dragon.in","r",stdin);
freopen("dragon.out","w",stdout);
memset(heads,-1,sizeof heads);
memset(head,-1,sizeof head);
memset(f,-1,sizeof f);
memset(child,-1,sizeof child);
scanf("%d%d%d",&n,&m,&k);
if(n-k<m-1){printf("-1");return 0;}
for(int i=1,x,y,z;i<n;i++){
scanf("%d%d%d",&x,&y,&z);
add1(x,y,z);
}
dfs(1,0);
for(int i=head[1];i!=-1;i=nxt[i])if(child[1][data[i]]!=-1){
ans+=dp(data[i],k-1,1);
break;
}
printf("%d\n",ans);
return 0;
}