hdu 5148 树形dp+分组背包问题

http://acm.hdu.edu.cn/showproblem.php?pid=5148

Problem Description

Long long ago,there is a knight called JayYe.He lives in a small country.This country is made up of n cities connected by n-1 roads(that means it‘s a tree).The king wants to reward JayYe because he beats the devil and save the princess.The king decide to give
JayYe exactly K cities as his daughter‘s dowry.

Here comes the question.Although JayYe beats the devil,his knee was injured.So he doesn‘t want to move too much,he wants his citys as close as possible,that is, JayYe wants the expected distance of his cities as small as possible.

The expected distance is defined as the expected distance between node u and node v,both u and v are randomly choose from JayYe‘s K cities equiprobably(that means first choose u randomly from JayYe’s K cities,then choose v randomly from JayYe’s K cities,so
the case u equals to v is possible).

Suppose you are the king,please determine the K cities so that JayYe is happy.

Because the author is lazy,you only need tell me the minimum expect distance.

Input

The first line contains a single integer T,indicating the number of test cases.

Each test case begins with two integers n and K,indicating the number of cities in this country,the number of cities the king gives to the knight.Then follows n-1 lines,each line contains three integers a,b,and c, indicating there is a road connects city a
and city b with length c.

[Technical Specification]

1 <= T <= 100

1 <= K <= min(50,n)

1 <= n <= 2000

1 <= a,b <= n

0 <= c <= 100000

Output

For each case, output one line, contain one integer, the minimum expect distance multiply K2.

Sample Input

1
2 2
1 2 1

Sample Output

2
/**
hdu 5148 树形dp+分组背包
题目大意:选出K个点v1,v2,...vK使得∑Ki=1∑Kj=1dis(vi,vj)最小.
解题思路:
考虑每条边的贡献,一条边会把树分成两部分,若在其中一部分里选择了x个点,则这条边被统计的次数为x*(K-x)*2.
那么考虑dp[u][i]表示在u的子树中选择了i个点的最小代价,有转移dp[u][i]=minKj=0(dp[u][i?j]+dp[v][j]+j*(K?j)*2*wu,v),式子中u为v的父亲,wu,v表示(u,v)这条边的长度.
把选取的点看做背包容量,每个子树看做一类物品,从每一类中最多选取一件物品,问背包可获得的最少价值。
时间复杂度O(nK^2).
*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int N=2055;
const long long inf = 200000 * 10000000LL;
int n,k;
struct note
{
    int v,w,next;
}edge[N*2];
int head[N],ip;
void init()
{
    memset(head,-1,sizeof(head));
    ip=0;
}
void addedge(int u,int v,int w)
{
    edge[ip].v=v,edge[ip].w=w,edge[ip].next=head[u],head[u]=ip++;
}
long long dp[N][55];
void dfs(int u,int pre)
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==pre) continue;
        dfs(v,u);
        for(int j=k;j>=0;j--)
        {
            for(int l=1;l<=j;l++)
            {
                dp[u][j]=min(dp[u][j],dp[u][j-l]+dp[v][l]+(k-l)*l*2*edge[i].w);
            }
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d%d",&n,&k);
        for(int i=0;i<n-1;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
       ///由于去最小,初始化除了dp[i][0]和dp[i][1]都要设为无穷大
       memset(dp,0,sizeof(dp));
       for (int i = 1; i <= n; i++)
        for (int j = 2; j <= k; j++)
             dp[i][j] = inf;
        dfs(1,-1);
        printf("%I64d\n",dp[1][k]);
    }
    return 0;
}
时间: 2024-12-21 13:19:00

hdu 5148 树形dp+分组背包问题的相关文章

hdu 1561 树形dp+分组背包

题意:就是给定n个点,每个地点有value[i]的宝物,而且有的宝物必须是另一个宝物取了才能取,问取m个点可以获得的最多宝物价值. 一个子节点就可以返回m个状态,每个状态表示容量为j(j<=m)时选最多的宝物,而一个子节点中只可以选择一个状态进行转移,每个节点有若干个子节点,问题就转换为分组背包,几个子节点就是几个分组背包,体积是选几个地点,价值是宝物价值. 状态转移方程: dp[v][1] = Money[v]; (v为叶子节点)                    dp[v][j] = m

hdu 4003 树形dp+分组背包

题意:求K个机器人从同一点出发,遍历所有点所需的最小花费 链接:点我 Sample Input 3 1 1 //3个点,从1出发,1个机器人 1 2 1 1 3 1 3 1 2 1 2 1 1 3 1 Sample Output 3 2 转移方程: dp[i][j]=min(dp[i][j],dp[i][j*k],dp[son[i]][k]+len(i,son[i])*k) 方程还是比较好写的,主要是要遍历所有的点 下面我们分析一下第一个样例 1 / \ / \ 2 3 我们派了一个机器人去3,

hdu 4003 树形dp+分组背包 2011大连赛区网络赛C

题意:求K个机器人从同一点出发,遍历所有点所需的最小花费 链接:点我 Sample Input 3 1 1 //3个点,从1出发,1个机器人 1 2 1 1 3 1 3 1 2 1 2 1 1 3 1 Sample Output 3 2 转移方程: dp[i][j]=min(dp[i][j],dp[i][j*k],dp[son[i]][k]+len(i,son[i])*k) 方程还是比较好写的,主要是要遍历所有的点 下面我们分析一下第一个样例 1 / \ / \ 2 3 我们派了一个机器人去3,

hdu4003 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4003 Problem Description Humans have discovered a kind of new metal mineral on Mars which are distributed in point‐like with paths connecting each of them which formed a tree. Now Humans launches k robots on

HDU ACM 4044 GeoDefense -&gt;树形DP+分组背包

题意:地图是一个编号为1-n的节点的树,节点1是敌方基地,其他叶节点是我方基地.敌人基地会出来敌人,为了防止敌人攻进我方基地,我们可以选择造塔.每个节点只能造一个塔,节点i有ki种塔供选择,价值和攻击力为price_i, power_i,攻击力power_i是让敌人经过这个节点时让敌人的HP减少power_i点.因此从敌人基地到我方任意一个基地的路径,这条路径上所有塔的攻击力之和,就是这个基地的抵抗力. 敌人攻击路径不确定,为了保护我方所有基地,需要确定所有基地中抵抗力最低的一个.我方只有数量为

hdu4044 树形dp+分组背包

http://acm.hdu.edu.cn/showproblem.php?pid=4044 Problem Description Tower defense is a kind of real-time strategy computer games. The goal of tower defense games is to try to stop enemies from reaching your bases by building towers which shoot at them

hdu 4123 树形DP+RMQ

http://acm.hdu.edu.cn/showproblem.php?pid=4123 Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses,

hdu 1250 树形DP

Anniversary party Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-27) Description There is going to be a party to celebrate the 80-th Anniversary of the Ural St

hdu 4276(树形dp)

题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏. 思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权.dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏. dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]); 被G++卡了好长时间,换成c++就过了. 代码如下: 1 #include <stdio.h> 2 #include <string.h