hdu 4003

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


你可能感兴趣的:(hdu 4003)