http://acm.hdu.edu.cn/showproblem.php?pid=4003
这题是比较好的树形dp题,dp[root][k] 表示派了k个机器人遍历了以root为根的树的最小代价,特殊的dp[root][0]表示派了一个机器人遍历后又回到root的最小代价
参考了 http://hi.baidu.com/dashi_h/blog/item/20dfb61cd8a4e10a6159f340.html
#include <cstdlib> #include <iostream> using namespace std; const int N=100005; int f[N][15],n,s,k; struct Node { int v,cost,nt; }e[20010]; int h[N],id; void addedge(int u,int v,int c) { e[id].cost=c; e[id].v=v; e[id].nt=h[u]; h[u]=id++; } void dfs(int root,int p) { for(int i=h[root];i!=-1;i=e[i].nt) { int v=e[i].v; if(v==p) continue; dfs(v,root); for(int j=k;j>=0;j--) { f[root][j]=f[root][j]+2*e[i].cost+f[v][0];//如果派了一个机器人在遍历完v子树后返回到root节点要特殊处理下 for(int t=1;t<=j;t++) { int tp=f[root][j-t]+f[v][t]+t*e[i].cost; if(tp<f[root][j]) f[root][j]=tp; } } } } int main(int argc, char *argv[]) { while(scanf("%d%d%d",&n,&s,&k)==3) { memset(f,0,sizeof(f)); memset(h,-1,sizeof(h)); id=0; for(int i=0;i<n-1;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a-1,b-1,c); addedge(b-1,a-1,c); } dfs(s-1,-1); printf("%d\n",f[s-1][k]); } return EXIT_SUCCESS; }