• P3177 [HAOI2015] 树上染色


    很好的一道树形dp

    具体哪些点选黑选白我们肯定是不知道的 但是题目最后要求的是求贡献

    所以只要我们能算出贡献就好了

    因为答案是线性的 简而言之就是 ∑每个边的贡献=总贡献

    考虑一条边的贡献

    边一侧的黑节点数另一侧的黑节点数边权+一侧的白节点数另一侧的白节点数边权

    设dp[u,i]表示u子树选i个黑点对总贡献的价值

    初始状态:dp[u][0]=dp[u][1]=0;

    转移方程:dp[u,k]=max(dp[u][k],dp[to][k-j]+val)

    val = j(k-j)w + (sz[v]-j)(n-k+j-sz[v])w

    w表示边权 sz[v]表示以v子树的节点数

    点击查看代码
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 2005;
    struct Edge{
    	int x, y, w, nxt;
    }e[maxn << 1 | 1];
    int n, m, cnt;
    int fr, to, haj;
    int head[maxn], siz[maxn];
    long long f[maxn][maxn];
    inline int read(void)
    {
    	int s = 0, w = 1;
    	char ch = getchar();
    	for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') w = -1;
    	for(; ch <= '9' && ch >= '0'; ch = getchar()) s = s * 10 + ch - '0';
    	return s * w;
    }
    inline void add(int x, int y, int w)
    {
    	e[++cnt].x = x;
    	e[cnt].y = y;
    	e[cnt].w = w;
    	e[cnt].nxt = head[x];
    	head[x] = cnt;	
    }
    void dfs(int x, int father)
    {
    	siz[x] = 1;   
    	f[x][0] = f[x][1] = 0; 
    	for(register int i = head[x]; i != -1; i = e[i].nxt)
    	{
    		int y = e[i].y;
    		if(y == father) continue; 
    		dfs(y, x); 
    		siz[x] += siz[y]; 
    		for(register int j = min(m, siz[x]); j >= 0; j--) 
    		{
    			for(register int k = 0; k <= min(j, siz[y]); k++) 
    			{
    				if(f[x][j - k] == -1) continue; 
    				long long val = 1ll * e[i].w * k * (m - k) + 1ll * e[i].w * (siz[y] - k) * (n - m - siz[y] + k); 
    				f[x][j] = max(f[x][j], f[x][j - k] + f[y][k] + val); 
    			} 
    		}
    	}
    }
    
    signed main()
    {
    	memset(head, -1, sizeof(head)); 
    	memset(f, -1, sizeof(f)); 
    	n = read(); m = read();
    	for(register int i = 1; i < n; i++) 
    	{
    		fr = read(); to = read(); haj = read();
    		add(fr, to, haj); 
    		add(to, fr, haj);
    	}
    	dfs(1, 0); 
    	cout << f[1][m] << '\n';
    	return 0;
    }
    
  • 相关阅读:
    一千行 MySQL 学习笔记
    linux学习(二)
    linux学习(二)
    内联元素
    内联因素1.默认内容撑开盒子大小
    定位absolute使内联支持宽高(块属性变为内联,内容默认撑开)margin auto 失效
    over
    float浮动问题:会造成父级元素高度坍塌;
    float的元素脱离文档流,但不完全脱离,只是提升了半层;
    float了的元素和内联元素不支持margin:auto
  • 原文地址:https://www.cnblogs.com/wzxbeliever/p/16100460.html
Copyright © 2020-2023  润新知