您的位置:首页 > 其它

hdu5148 树形dp,分组背包

2015-05-18 17:45 274 查看
dp[i][j]表示以i为根节点的子树中选j个城市贡献边长的最小值,怎样由子树向上递推呢,子树是一个天然的组,dp[u][j]可以这样理解,u子树容量为j是由上一层dp[u][j-f]推出的,应用了滚动数组。

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ull;
typedef long long ll;
const int maxn=100005;
ll dp[2005][55];
vector<pii>g[2005];
int n,k;
void dfs(int u,int fa)
{
    for(int i=0;i<g[u].size();i++)
    {
        if(g[u][i].first==fa)
            continue;
        dfs(g[u][i].first,u);
        int v=g[u][i].first;
        for(int j=k;j>=0;j--)
        {
            for(int f=0;f<=j;f++)
            {
                dp[u][j]=min(dp[u][j],dp[u][j-f]+dp[v][f]+f*(k-f)*2*g[u][i].second);
            }
        }
    }
}
int main()
{
    int t;
    int a,b,c;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            g[i].clear();
        for(int i=0;i<n-1;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            g[a].push_back(pii(b,c));
            g[b].push_back(pii(a,c));
        }
        memset(dp,-1,sizeof(dp));
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=k;j++)
            {
                if(j<=1)
                    dp[i][j]=0;
                else
                    dp[i][j]=inf;
            }
        }
        dfs(1,-1);
        cout<<dp[1][k]<<endl;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: