• [HAOI2015]树上染色


    题意

    给一棵(n)个点的边带权的树,要求选(k)个点染成白色,其他点为黑色,最大化(黑点两两距离+白点两两距离),((nleq 2000))

    思路

    一道好题,思路不容易get,但是想出来之后很简单

    一般树形DP的套路:设(f_{rt,i})表示以(rt)为根的子树选(i)个点染成白色,这棵子树白点两两距离和;然后发现不会转移了qwq

    为什么这样做不行呢?因为这棵子树白点的贡献并不仅限于这棵子树,也就是说这棵子树中的白点需要和子树外的白点统计距离,但是状态的定义使得我们只能统计子树内的白点两两距离,合并状态的时候由于不知道白点的分布而不能求子树间白点的贡献


    考虑边的贡献,即可完美解决这个问题

    一条边的贡献为:(wi imes) (() 一边的白点数( imes)另一边的白点数(+)一边的黑点数( imes)另一边的黑点数()),于是设(f_{rt,i})表示以(rt)为根的子树中选择(i)个点染为白色时,这棵子树中所有边的贡献

    可以发现转移就是个树形背包,于是就这么搞就完事了

    Code

    #include<bits/stdc++.h>
    #define N 2005
    #define Min(x,y) ((x)<(y)?(x):(y))
    #define Max(x,y) ((x)>(y)?(x):(y))
    using namespace std;
    typedef long long ll;
    int n,m,size[N];
    ll f[N][N];
    struct Edge
    {
    	int next,to;
    	ll dis;
    }edge[N<<1];int head[N],cnt=1;
    void add_edge(int from,int to,ll dis)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].dis=dis;
    	head[from]=cnt;
    }
    
    template <class T>
    void read(T &x)
    {
    	char c; int sign=1;
    	while((c=getchar())>'9'||c<'0') if(c=='-') sign=-1; x=c-48;
    	while((c=getchar())>='0'&&c<='9') x=(x<<1)+(x<<3)+c-48; x*=sign;
    }
    void dfs(int rt,int fa)
    {
    	size[rt]=1;
    	f[rt][0]=f[rt][1]=0;
    	for(int i=head[rt];i;i=edge[i].next)
    	{
    		int v=edge[i].to;
    		if(v==fa) continue;
    		dfs(v,rt);
    		size[rt]+=size[v];
    		for(int j=Min(size[rt],m);j>=0;--j)
    		{
    			for(int k=0;k<=Min(j,size[v]);++k)
    			{
    				ll val = edge[i].dis*((ll)k*(m-k) + (ll)(size[v]-k)*(n-m-size[v]+k));
    				f[rt][j]=Max(f[rt][j] , f[v][k] + f[rt][j-k] + val);
    			}
    		}
    	}
    }
    int main()
    {
    	read(n);read(m);
    	for(int i=1;i<n;++i)
    	{
    		int x,y; ll z;
    		read(x);read(y);read(z);
    		add_edge(x,y,z);
    		add_edge(y,x,z);
    	}
    	memset(f,-50,sizeof(f));
    	dfs(1,0);
    	cout<<f[1][m]<<endl;
    	return 0;
    }
    
  • 相关阅读:
    Android studio ocr初级app开发问题汇总(含工程代码)
    面试题思路,25匹马 5个跑道取前三,前五,最少比赛次数--七次
    中国计算机学会推荐国际学术会议和期刊目录(CCF)2019年
    swift 数组部分排序
    SceneKit下关于修改SCNNode 的Shader展示自定义图形
    汇编语言实现字母下落效果
    组合数计算-java
    miniblast_hash算法c语言实现
    日常开发知识点备忘
    骑士周游问题跳马问题C#实现(附带WPF工程代码)
  • 原文地址:https://www.cnblogs.com/Chtholly/p/11789305.html
Copyright © 2020-2023  润新知