BZOJ 1369 Gem - 树型dp

传送门

题目大意:

给一棵树上每个点一个正权值,要求父子的权值不同,问该树的最小权值和是多少。

题目分析:

证不出来最少染色数,那就直接信仰用20来dp吧:dp[u][i]表示u节点权值赋为i时u子树的权值最小值,$$dp[u][i] = \sum{max{dp[v][j]}} + i (i != j)$$。

code

#include<bits/stdc++.h>
using namespace std;
#define maxn 10050
#define oo 0x3f3f3f3f
int n, dp[maxn][30], ans;
vector<int> adj[maxn];

inline int DP(int u, int f, int val){
	if(dp[u][val] != -1) return dp[u][val];
	dp[u][val] = val;
	for(int e = adj[u].size()-1; e >= 0; e--){
		int v = adj[u][e];
		if(v == f) continue;
		int mn = oo;
		for(int i = 1; i <= 20; i++){
			if(i != val)
				mn = min(mn, DP(v, u, i));
		}
		dp[u][val] += mn;
	}
	return dp[u][val];
}

int main(){
	scanf("%d", &n);
	for(int i = 1; i <= n - 1; i++){
		int x, y; scanf("%d%d", &x, &y);
		adj[x].push_back(y), adj[y].push_back(x);
	}
	memset(dp, -1, sizeof dp);
	ans = oo;
	for(int i = 1; i <= 20; i++)
		ans = min(ans, DP(1, 0, i));
	printf("%d", ans);
	return 0;
} 
posted @ 2017-10-21 19:54  CzYoL  阅读(195)  评论(0编辑  收藏  举报