题目大意:一棵树,相邻两点不能同色,现有红黄蓝以及各点涂各种颜色的价值,请问涂色后最大价值是多少?
f[i][j]表示结点i涂颜色j子树的最大价值。如果i点图j色,那么儿子结点只能图另外2中颜色,取最大值即可。
最终答案是f[1][0]、f[1][1]、f[1][2]里面找。
#include <bits/stdc++.h> #define LL long long #define N 100005 using namespace std; LL n, m, i, j, k, a, b, ans; LL h[N], v[N][3], f[N][3], u[N]; struct AB{ LL a, b, n; } d[N*2]; void cun(LL a, LL b){ d[++k].a = a, d[k].b = b; d[k].n = h[a], h[a] = k; } void dfs(LL a, LL p){ LL b, c, i, j, k; if(u[a]) return; u[a] = 1;//已经搜过,已知该点涂色的信息 for(c=0; c<3; c++){ f[a][c] = v[a][c]; for(i=h[a]; i; i=d[i].n){ b = d[i].b; if(b != p){//是儿子 dfs(b, a);//处理好儿子的信息 for(j=k=0; j<3; j++){//枚举儿子的颜色 if(j == c) continue; k = max(k, f[b][j]); } f[a][c] += k; } } } } int main(){ scanf("%lld", &n); for(i=1; i<n; i++){ scanf("%lld%lld", &a, &b); cun(a, b); cun(b, a); } for(i=1; i<=n; i++){ for(j=0; j<3; j++){ scanf("%lld", &v[i][j]); } } dfs(1, 0); ans = max(f[1][0], max(f[1][1], f[1][2])); printf("%lld\n", ans); return 0; }