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]);
}

  

posted @ 2017-04-13 21:44  SfailSth  阅读(141)  评论(0编辑  收藏  举报