zoukankan      html  css  js  c++  java
  • [BZOJ4033]:[HAOI2015]树上染色(树上DP)

    题目传送门


    题目描述

    有一棵点数为N的树,树边有边权。给你一个在0~N之内的正整数K,你要在这棵树中选择K个点,将其染成黑色,并将其他的N-K个点染成白色。将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间距离的和的收益。
    问收益最大值是多少。


    输入格式

    第一行两个整数NK
    接下来N-1行每行三个正整数frtodis,表示该树中存在一条长度为dis的边(fr,to)
    输入保证所有点之间是联通的。
    N<=20000<=K<=N


    输出格式

    输出一个正整数,表示收益的最大值。


    样例

    样例输入:

    5 2
    1 2 3
    1 5 1
    2 3 1
    2 4 2

    样例输出:

    17


    数据范围与提示

    样例解释:将点12染黑就能获得最大收益。

    N≤20000≤K≤N


    题解

    看提第一眼,树上DP

    定义dp[i][j]表示以i为根节点的子树上有j个黑点的最大收益。

    那么,显然,这条边对答案的贡献只与它的子树内、外有几个黑点、白点有关,与它的子树的子树无关。

    设点x的子树和为size[x],如果它的子树里有black个黑点,那么它的子树中就有size[x]-black个白点,它的子树外就有k-black个黑点,n-k-(size[x]-black)个白点,那么,这条边对答案的贡献就为{black×(size[x]-black)+(k-black)×[n-k-(size[x]-black)]}×边权。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    struct rec
    {
    	int nxt;
    	int to;
    	int w;
    }e[4000];
    int head[2001],cnt;
    int n,b;
    long long dp[2001][2001],flag[2001];//记得开long long……
    int size[2001];
    void add(int x,int y,int w)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	e[cnt].w=w;
    	head[x]=cnt;
    }
    void dfs(int x)//树上DP
    {
    	size[x]=1;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		if(size[e[i].to])continue;
    		dfs(e[i].to);
    		memset(flag,0,sizeof(flag));
    		for(int j=0;j<=min(b,size[x]);j++)
    			for(int k=0;k<=min(b,size[e[i].to])&&j+k<=b;k++)
    				flag[j+k]=max(flag[j+k],dp[x][j]+dp[e[i].to][k]+(k*(b-k)+1LL*(size[e[i].to]-k)*(n-b-size[e[i].to]+k))*e[i].w);//转移
    		for(int j=0;j<=b;j++)dp[x][j]=flag[j];
    		size[x]+=size[e[i].to];
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&b);
    	for(int i=1;i<n;i++)
    	{
    		int fr,to,dis;
    		scanf("%d%d%d",&fr,&to,&dis);
    		add(fr,to,dis);
    		add(to,fr,dis);
    	}
    	dfs(1);
    	cout<<dp[1][b]<<endl;
    	return 0;
    }
    

    rp++

  • 相关阅读:
    redis集群部署之codis 维护脚本
    redis 数据库维护之 key 大小获取
    用HAProxy和KeepAlived构建高可用的反向代理
    blender 2.8 [学习笔记-028] 编辑模式- 所有面整体切分
    blender 2.8 [学习笔记-027] 编辑模式- 切分
    blender 2.8 [学习笔记-026] 编辑模式- 切割
    blender 2.8 [学习笔记-025] 编辑模式- 偏移环切边
    blender 2.8 [学习笔记-024] 编辑模式- 环切
    blender 2.8 [学习笔记-023] 编辑模式-倒角
    blender 2.8 [学习笔记-023] 编辑模式-内插面
  • 原文地址:https://www.cnblogs.com/wzc521/p/11191089.html
Copyright © 2011-2022 走看看