码迷,mamicode.com
首页 > 其他好文 > 详细

HAOI2015树上染色

时间:2015-05-22 08:12:44      阅读:117      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:给树上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]);
}
View Code

 

HAOI2015树上染色

标签:

原文地址:http://www.cnblogs.com/Rivendell/p/4521360.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!