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

    (large{咕咕咕}\)
    (large{题目链接})
    (\)
    (Large extbf{Solution: } large{首先如果直接计算,由于k个点并不固定且还要计算两两间的距离,不好统计答案。\最直接设f[i][j]表示以i为根的树中选j个黑点的最优答案,但是发现无法转移,\因为全局最优解和局部最优没什么关系,于是考虑对贡献去做DP。\考虑用状态f[i][j]表示i为根的树中选j个黑点对答案的贡献是多少。转移就容易了,\每条边对答案的贡献即是 两边黑点的数量与边权之积 + 两边白点数量与边权之积。})
    (\)
    (Large extbf{Summary: } large{1.当问题不满足最优子结构时,可以考虑DP每个子问题对答案的贡献。\2.很多时候刷表法难以滚动数组,需要转化成填表法。})
    (\)
    (Large extbf{Code: })

    #include <bits/stdc++.h> 
    #define gc() getchar() 
    #define LL long long
    #define rep(i, a, b) for (int i = (a); i <= (b); ++i)
    using namespace std;
    const int N = 2e3 + 5;
    int n, k, cnt, head[N], size[N];
    LL f[N][N];
    
    struct Edge {
    	int to, next, val;
    }e[N << 1];
    
    inline int read() {
    	int x = 0, flg = 1;
    	char ch = gc();
    	while (!isdigit(ch)) {
    		if (ch == '-') flg = -1;
    		ch = gc();
    	}
    	while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
    	return x * flg; 
    }
    
    inline void add(int x, int y, int w) {
    	e[++cnt].to = y;
    	e[cnt].next = head[x];
    	e[cnt].val = w;
    	head[x] = cnt;
    }
    
    inline void dfs(int x, int fa) {
    	size[x] = 1;
    	f[x][0] = f[x][1] = 0;
    	for (int i = head[x]; i ; i = e[i].next) {
    		int u = e[i].to;
    		if (u == fa) continue;
    		dfs(u, x);
    		size[x] += size[u];
    	}
    	for (int i = head[x]; i ; i = e[i].next) { 
    		int u = e[i].to;
    		if (u == fa) continue;
    		for(int j = min(k, size[x]); j >= 0; --j) 
    			for(int p = 0; p <= min(j, size[u]); ++p) {
    				if (f[x][j - p] != - 1) {
    					LL val = 1LL * p * (k - p) * e[i].val + 1LL * (size[u] - p) * (n - k - size[u] + p) * e[i].val;
    					f[x][j] = max(f[x][j], f[x][j - p] + val + f[u][p]);
    				}
    			}
        }
    }
    
    int main() {
    	n = read(), k = read();
    	int x, y, w;
    	rep(i, 2, n) x = read(), y = read(), w = read(), add(x, y, w), add(y, x ,w);
    	memset(f, -1, sizeof (f));
    	dfs(1, 0);
    	printf("%lld
    ", f[1][k]);
    	return 0;
    }
    
  • 相关阅读:
    每日博客
    每日博客之十一月读书笔记1
    每日博客
    今日收获
    今日收获
    今日收获
    动手动脑10.21
    今日收获
    今日收获
    8月21日
  • 原文地址:https://www.cnblogs.com/Miraclys/p/12576649.html
Copyright © 2011-2022 走看看