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

 

posted @ 2019-08-07 19:52  PYWBKTDA  阅读(95)  评论(0编辑  收藏  举报