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;
}