标签:
题目大意:给树上n个点染k个黑色,求黑点之间、白点之间距离和的最大值。
思路:感觉是树形dp,但是觉得转移的时候很难受。后来听到fye大神的背包,就开始想背包方向想,发现多重背包可以解决。我们dfs一个孩子之后就可以进行背包了。但是赋初值的时候,要给f[u][0]和f[u][1]都赋为0,因为对于u这个根节点,我们可以涂两种颜色,初始值中的f[u][0]表示把它涂成白色,而f[u][1]表示涂成黑色,其他都是-∞就可以了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #define maxnode 2001 using namespace std; int point[maxnode]={0},next[maxnode*2]={0},en[maxnode*2]={0},tot=0,siz[maxnode]={0},n,kk; long long va[maxnode*2]={0},f[maxnode][maxnode]={0}; bool visit[maxnode]={false}; void add(int u,int v,long long st) { ++tot;next[tot]=point[u];point[u]=tot;en[tot]=v;va[tot]=st; ++tot;next[tot]=point[v];point[v]=tot;en[tot]=u;va[tot]=st; } void dfs(int u) { int i,j,k,t; long long sum; siz[u]=1;visit[u]=true;f[u][0]=f[u][1]=0; for (i=point[u];i;i=next[i]) if (!visit[j=en[i]]) { dfs(j);siz[u]+=siz[j]; for (k=siz[u];k>=0;--k) for (t=0;t<=siz[j]&&t<=k;++t) { sum=f[u][k-t]+f[j][t]+va[i]*(long long)(t*(kk-t))+va[i]*(long long)((siz[j]-t)*(n-kk-(siz[j]-t))); f[u][k]=max(f[u][k],sum); } } } int main() { int i,j,u,v; long long st; scanf("%d%d",&n,&kk); for (i=1;i<n;++i) { scanf("%d%d%lld",&u,&v,&st); add(u,v,st); } for (i=0;i<maxnode;++i) for (j=0;j<maxnode;++j) f[i][j]=-999999999999; dfs(1); printf("%lld\n",f[1][kk]); }
标签:
原文地址:http://www.cnblogs.com/Rivendell/p/4521360.html