题意:n个结点的树,每条边都有边权,问保留根节点1和Q条边时,最大的边权和是多少?
保留Q条边 即保留Q+1个点,dp[i][j] 以i为根的子树中选j个的最大价值
dp[i][j]=max(dp[i][j],dp[v][k]+dp[i][j-k])
递推时,dp[i][j-k]为不含子树v,选j-k的最大价值
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N=2e3+20;
int n,q,sz[N];
vector<pii> e[N];
int dp[N][N];//
int dfs_size(int u,int fa)
{
sz[u]=1;
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i].first;
if(v==fa) continue;
dfs_size(v,u);
sz[u]+=sz[v];
}
return sz[u];
}
void dfs(int u,int fa)
{
int v,w;
for(int i=0;i<e[u].size();i++)
{
v=e[u][i].first,w=e[u][i].second;
if(v==fa) continue;
dfs(v,u);
for(int j=sz[u];j>1;j--)//
{
for(int k=1;k<j;k++)
{
//选v则边(u,v)被选
dp[u][j]=max(dp[u][j],dp[v][k]+dp[u][j-k]+w);
//dp[u][j-k]为不含子树v,选j-k的最大价值
}
}
}
}
int main()
{
while(cin>>n>>q)
{
memset(sz,0,sizeof(sz));
for(int i=1;i<=n;i++)
e[i].clear();
int u,v,w;
for(int i=1;i<=n-1;i++)
{
cin>>u>>v>>w;
e[u].push_back(pii(v,w));
e[v].push_back(pii(u,w));
}
dfs_size(1,-1);
dfs(1,-1);
cout<<dp[1][q+1]<<endl;
}
return 0;
}