很经典的一道树状DP题,新手(比如我这种)拿来学习和试手的一道好题,首先推出状态转移方程,然后……
就没有然后了。
选择节点类方程
f[u][0] = sum(max(f[v][1], f[v][0]));(v是u的儿子)
你不去,那下属可以想去就去。
f[u][1] = sum(f[v][0]) + happy[u];(v是u的儿子)
你去了,那下属就一定不会去。
代码实现如下:
void dp(int u) { f[u][0] = 0; f[u][1] = happy[u]; for (int i = 0; i < son[u].size(); i++) { int v = son[u][i]; dp(v); f[u][0] += max(f[v][0], f[v][1]); f[u][1] += f[v][0]; } }
不过在这之前需要先找到根结点root,可以用一个bool数组。每读入一个结点x,如果其有上司,则bool[x]赋值为1,然后for循环,bool值为0的即为根结点root。
代码实现如下:
for (int i = 0; i < n - 1; i++) { int u, v; u = read(); v = read(); son[v].push_back(u); vis[u] = 1; } for (int i = 0; i < n; i++) if (!vis[i]) { root = i; break; } dp(root);