[bzoj4033]树上染色
令f[i][j]表示以i为根的子树中选择j个点颜色为黑色的最大收益,$f[i][j+t]=max(f[i][j]+f[son][t]+val(i->son)$,其中$val(i->son)=(k-t)*t+(sz[son]-t)*(n-k-sz[son]+t)$,时间复杂度为$\sum_{i=1}^{n}\sum_{son}(sz[i]-sz[son])\cdot sz[son]=\sum_{i=1}^{n}sz[i]^{2}-\sum_{son=2}^{n}sz[son]^{2}=n^{2}$(sz[i]表示以i为根的子树大小)
#include<bits/stdc++.h> using namespace std; #define N 2005 struct ji{ int nex,to,len; }edge[N<<1]; int E,n,m,x,y,z,head[N],sz[N]; long long g[N],f[N][N]; void add(int x,int y,int z){ edge[E].nex=head[x]; edge[E].to=y; edge[E].len=z; head[x]=E++; } void dfs(int k,int fa){ sz[k]=1; for(int i=head[k];i!=-1;i=edge[i].nex) if (edge[i].to!=fa){ int v=edge[i].to; dfs(v,k); for(int j=sz[k];j>=0;j--) for(int t=sz[v];t>=0;t--) f[k][j+t]=max(f[k][j+t],f[k][j]+f[v][t]+1LL*edge[i].len*((m-t)*t+(sz[v]-t)*(n-m-sz[v]+t))); sz[k]+=sz[v]; } } int main(){ scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); for(int i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&z); add(x,y,z); add(y,x,z); } dfs(1,0); printf("%lld",f[1][m]); }