其实这样的dp可以先想dp[i][t][j],即前t个子树的情况,这样更方便理解。
不过复杂度分析确实比较厉害。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 2050 #define maxe 4050 #define inf 0x7f7f7f7f7f7f7f7fLL using namespace std; struct edge { long long v,w,nxt; }e[maxe]; long long n,k,x,y,z,g[maxv],nume=0,dp[maxv][maxv],size[maxv]; void addedge(long long u,long long v,long long w) { e[++nume].v=v;e[nume].w=w; e[nume].nxt=g[u];g[u]=nume; } void dfs1(long long x,long long fath) { long long tmp[4050];size[x]=1; for (long long i=g[x];i;i=e[i].nxt) { long long v=e[i].v; if (v!=fath) { dfs1(v,x); for (long long j=0;j<=size[x]+size[v];j++) tmp[j]=-inf; for (long long a=0;a<=size[x];a++) for (long long b=0;b<=size[v];b++) tmp[a+b]=max(tmp[a+b],dp[x][a]+dp[v][b]+e[i].w*(b*(k-b)+(size[v]-b)*(n-k-size[v]+b))); size[x]+=size[v]; for (long long j=0;j<=size[x];j++) dp[x][j]=tmp[j]; } } } int main() { scanf("%lld%lld",&n,&k); for (long long i=1;i<=n-1;i++) { scanf("%lld%lld%lld",&x,&y,&z); addedge(x,y,z);addedge(y,x,z); } dfs1(1,-1); printf("%lld\n",dp[1][k]); return 0; }