zoukankan      html  css  js  c++  java
  • [HAOI2015]树上染色

    树形背包dp,求整体贡献。

    别的树形dp一般是考虑子树的最优解,但这道题由于每次转移都会对全局提供贡献,所以我们考虑贡献。令dp[i][j]表示以i为根的子树选j个点最多能为最终答案做的贡献。那么这道题就转化为了树形背包dp,转移方程:

    	int tmp = k*(m-k)*w + (size[v]-k)*(n-m+k-size[v])*w;(求一条边对答案的贡献)
            dp[s][j]=max(dp[s][j],dp[s][j-k]+dp[v][k]+tmp);(背包的转移,不过权值换为了对答案的贡献)
    

    注意特判 if (dp[s][j-k]==-1) continue;

    code

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #include<stack>
    #include<bitset>
    #include<cmath>
    #define int long long 
    using namespace std;
    const int maxn=2006;
    const int k=2333;
    struct hzw
    {
      int to,next,v;
    }e[maxn*2];
    int head[maxn*2],cur,val[maxn];
    inline void add(int a,int b,int c)
    {
    	e[cur].to=b;
    	e[cur].next=head[a];
    	e[cur].v=c;
    	head[a]=cur++;
    }
    int dp[3001][3001],n,m,size[maxn];
    inline void dfs(int s,int fa)
    {
        for (int i=0;i<=m;++i) dp[s][i]=-1;
        dp[s][0]=dp[s][1]=0;
        size[s]=1;
        for (int i=head[s];i!=-1;i=e[i].next)
        {
            if (e[i].to==fa) continue;
            dfs(e[i].to,s);
            size[s]+=size[e[i].to];
        }
        for (int i=head[s];i!=-1;i=e[i].next)
        {
            int v=e[i].to,w=e[i].v;
            if (v==fa) continue;
            for (int j=min(size[s],m);j>=0;j--)
                for (int k=0;k<=min(j,size[v]);++k)
                {
                	if (dp[s][j-k]==-1) continue;
            		int tmp = k*(m-k)*w + (size[v]-k)*(n-m+k-size[v])*w;
                    dp[s][j]=max(dp[s][j],dp[s][j-k]+dp[v][k]+tmp);
                } 
        }
    }
    signed main()
    { 
    	memset(head,-1,sizeof(head));
        cin>>n>>m;
        for (int i=1,a,b,c;i<=n-1;++i)
        {
            scanf("%lld%lld%lld",&a,&b,&c);
    //        cout<<a<<" "<<b<<" "<<c<<"shit"<<endl;
            add(a,b,c);
            add(b,a,c);
        }
        dfs(1,1);
        cout<<dp[1][m];
    }
    

    收获:

    1、树形背包问题的常见转移套路。
    2、如果改变状态会对整体答案造成影响,考虑转移对答案的贡献。

  • 相关阅读:
    树莓派进阶之路 (029)
    C语言学习笔记 (010)
    树莓派进阶之路 (028)
    C语言学习笔记 (009)
    虚拟内存和swap分区的关系
    树莓派进阶之路 (027)
    树莓派进阶之路 (026)
    C语言学习笔记 (008)
    ubuntu下安装gedit插件
    Ubuntu终端命令行播放音乐(mp3)
  • 原文地址:https://www.cnblogs.com/bullshit/p/9632515.html
Copyright © 2011-2022 走看看