【树形DP】HDU 4003 Find Metal Mineral
通道:http://acm.hdu.edu.cn/showproblem.php?pid=4003
题意:边权树. 有K个机器人从S点出发, 问让机器人遍历所有边,最少花费值多少
思路:dp[i][j]表示以i为根的树用掉j个人。dp[i][0]表示用了一个人又回到上面的点,然后就是分组背包,每个组必选一个,这就有个特殊技巧,就是我们先将dp[son][0]放进背包,如果该组里有更好的选择,那么就会换掉这个物品,否则的话这个物品就是最好的选择。这样保证每组必定选了一个
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<algorithm> #include<string.h> #include<iostream> using namespace std; const int MAXN=10010; struct Node { int to; int next; int cost; }edge[MAXN*2]; int head[MAXN]; int tol; int dp[MAXN][11]; void init() { memset(head,-1,sizeof(head)); tol=0; memset(dp,0,sizeof(dp)); } void add(int a,int b,int val) { edge[tol].to=b; edge[tol].cost=val; edge[tol].next=head[a]; head[a]=tol++; edge[tol].to=a; edge[tol].cost=val; edge[tol].next=head[b]; head[b]=tol++; } int N,K; void dfs(int u,int pre) { for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v==pre)continue; dfs(v,u); for(int k=K;k>=0;k--) { dp[u][k]+=dp[v][0]+2*edge[i].cost; for(int j=1;j<=k;j++) dp[u][k]=min(dp[u][k],dp[u][k-j]+dp[v][j]+j*edge[i].cost); } } } int main() { int S; int a,b,val; while(scanf("%d%d%d",&N,&S,&K)!=EOF) { init(); for(int i=1;i<N;i++) { scanf("%d%d%d",&a,&b,&val); add(a,b,val); } dfs(S,-1); printf("%d\n",dp[S][K]); } return 0; }