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