BZOJ 4033: [HAOI2015]树上染色

题解:

树形DP

思路,考虑每条边的贡献,即这条边两边的黑点数量相乘+白点数量相乘再成边长

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=2009;
typedef long long Lint;

int n,m;

int cntedge=0;
int head[maxn]={0};
int to[maxn<<1],nex[maxn<<1],dist[maxn<<1];
void Addedge(int x,int y,int z){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	dist[cntedge]=z;
	head[x]=cntedge;
}

Lint f[maxn][maxn];
Lint g[maxn];
int siz[maxn];
void Dp(int x,int fa){
	
	for(int i=head[x];i;i=nex[i]){
		int v=to[i];
		if(to[i]==fa)continue;
		Dp(v,x);
		memset(g,0,sizeof(g));
		for(int j=0;j<=siz[x];++j){
			for(int k=0;k<=siz[v];++k){
				Lint tm=max(f[v][k],k?f[v][k-1]:0)+f[x][j]+1LL*k*(m-k)*dist[i]+1LL*(siz[v]-k)*(n-m-siz[v]+k)*dist[i];
				g[j+k]=max(g[j+k],tm);
			}
		}
		siz[x]+=siz[v];
		for(int j=0;j<=siz[x];++j)f[x][j]=g[j];
	}
	++siz[x];
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n-1;++i){
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		Addedge(x,y,z);
		Addedge(y,x,z);
	}
	
	Dp(1,0);
	cout<<max(f[1][m],f[1][m-1]);
	cout<<endl;
	return 0;
}

  

posted @ 2018-03-13 19:52  ws_zzy  阅读(160)  评论(0编辑  收藏  举报