树形DP要有自己的风格,转二叉树是基础,考虑边界最头疼。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int point[303],next[603],v[603],c[603],cnt=0,N,M,K,f[303][303][2],d[303],con[303],pre[303]; 6 int l[303],r[303]; 7 bool p[303]; 8 void insect(int x,int y,int z){next[cnt]=point[x];point[x]=cnt;v[cnt]=y;c[cnt]=z;cnt++;} 9 void dfs(int x) 10 { 11 int i,j=-1; 12 for (i=point[x];i!=-1;i=next[i]) 13 if (p[v[i]]==0) 14 { 15 p[v[i]]=1; 16 if (l[x]==0) l[x]=v[i],d[v[i]]=c[i],pre[v[i]]=0,j=l[x]; else 17 { 18 r[j]=v[i]; d[v[i]]=c[i]; pre[r[j]]=j; j=r[j]; 19 } 20 } 21 if (j==-1) return; 22 dfs(j); con[j]=con[l[j]]+1; 23 while (pre[j]!=0) j=pre[j],dfs(j),con[j]=con[l[j]]+con[r[j]]+1; 24 } 25 int dp(int x,int k,int t) 26 { 27 if (x==0) return 0; 28 if (f[x][k][t]!=-1) return f[x][k][t]; 29 int i,l1,r1,num=1000000000; 30 for (i=0;i<k;++i) 31 if ((i<=con[l[x]])&&(k-1-i<=con[r[x]])) 32 { 33 l1=dp(l[x],i,1); 34 r1=dp(r[x],k-1-i,t); 35 num=min(num,l1+r1+(t==1)*d[x]); 36 } 37 for (i=0;i<=k;++i) 38 if ((i<=con[l[x]])&&(k-i<=con[r[x]])) 39 { 40 l1=dp(l[x],i,0); 41 r1=dp(r[x],k-i,t); 42 num=min(num,l1+r1+(M==2)*(t==0)*d[x]); 43 }f[x][k][t]=num; 44 return num; 45 } 46 int main() 47 { 48 memset(point,-1,sizeof(point)); 49 memset(next,-1,sizeof(next)); 50 memset(f,-1,sizeof(f)); 51 memset(v,0,sizeof(v)); 52 memset(c,0,sizeof(c)); 53 memset(p,0,sizeof(p)); 54 scanf("%d %d %d\n",&N,&M,&K); 55 if (K+M-1>N) {printf("-1\n");return 0;} 56 int i,a,b,c; 57 for (i=1;i<N;++i) 58 { 59 scanf("%d %d %d\n",&a,&b,&c); 60 insect(a,b,c);insect(b,a,c); 61 }p[1]=1; dfs(1); 62 printf("%d\n",dp(l[1],K-1,1)); 63 return 0; 64 }