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;
}