BZOJ 4033 [HAOI2015]树上染色 ——树形DP
可以去UOJ看出题人的题解。
这样的合并,每一个点对只在lca处被考虑到,复杂度$O(n^2)$
#include <map> #include <ctime> #include <cmath> #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define F(i,j,k) for (ll i=j;i<=k;++i) #define D(i,j,k) for (ll i=j;i>=k;--i) #define ll long long ll h[5005],to[5005],ne[5005],en=0,w[5005]; void add(ll a,ll b,ll c) {to[en]=b;ne[en]=h[a];w[en]=c;h[a]=en++;} ll n,k,tmp[2005],m; ll dp[2005][2005]; ll siz[2005]; void Tree_DP(ll o,ll fa) { dp[o][0]=dp[o][1]=0; siz[o]=1; for (ll i=h[o];i>=0;i=ne[i]) if (to[i]!=fa) { Tree_DP(to[i],o); memset(tmp,-0x3f3f3f3f,(siz[o]+siz[to[i]]+2)*sizeof (ll)); for (ll j=0;j<=siz[o];++j) for (ll k=0;k<=siz[to[i]];++k) tmp[j+k]=max((ll)tmp[j+k],(ll)dp[o][j]+dp[to[i]][k]+(ll)w[i]*(k*(m-k)+(siz[to[i]]-k)*(n-m-(siz[to[i]]-k)))); siz[o]+=siz[to[i]]; for (ll j=0;j<=siz[o];++j) dp[o][j]=max((ll)tmp[j],dp[o][j]); } } int main() { memset(h,-1,sizeof h); scanf("%lld%lld",&n,&m); F(i,2,n) { ll a,b,c; scanf("%lld%lld%lld",&a,&b,&c); add(a,b,c); add(b,a,c); } memset(dp,-0x3f3f3f3f,sizeof (dp)); Tree_DP(1,0); printf("%lld\n",dp[1][m]); }