树形背包dp
dp我会讲嘛?还是这么难的。。
大概思路就是一条边的贡献是它连接的两个块中的颜色个数bulabula的算了,盗个题解吧(背景是我的233)
代码(我的是STL版的)
//By AcerMo
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lli long long int
using namespace std;
const int M=3050;
struct edge
{
int to,cost;
}now;
int n,k,siz[M];
lli dis[M][M];
vector<edge>g[M];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch>'9'||ch<'0') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
void dfs(int x, int fa)
{
siz[x]=1;dis[x][0]=dis[x][1]=0;
for (int i=0;i<g[x].size();i++)
{
int go=g[x][i].to;
if (go==fa) continue;
dfs(go,x);siz[x]+=siz[go];
}
for (int i=0;i<g[x].size();i++)
{
int v=g[x][i].to,w=g[x][i].cost;
if (v==fa) continue;
for (int p=min(siz[x],k);p>=0;p--)
for (int q=0;q<=min(p,siz[v]);q++)
if (dis[x][p-q]>=0)
{
lli val= 1ll*(q*(k-q)+(siz[v]-q)*(n-k+q-siz[v]))*w;
dis[x][p]=max(dis[x][p],dis[x][p-q]+dis[v][q]+val);
}
}
return ;
}
int main()
{
n=read();k=read();
for (int i=1;i<n;i++)
{
int a=read(),b=read(),c=read();
now.to=b;now.cost=c;g[a].push_back(now);
now.to=a;now.cost=c;g[b].push_back(now);
}
memset(dis,-1,sizeof(dis));
dfs(1,0);
printf("%lld\n",dis[1][k]);
return 0;
}