解题报告 『没有上司的舞会(树形动规)』
很经典的一道树状DP题,很适合新手(比如我)用来学习或练手,首先推出状态转移方程,然后……
就没有然后了。
选择节点类方程:
dp[u][0] = sum(max(dp[v][1], dp[v][0]));(v是u的儿子)
你不去,那下属可以去或不去。
dp[u][1] = sum(dp[v][0]) + happy[u];(v是u的儿子)
你去了,那下属就一定不会去。
代码实现如下:
void dp(int u) { f[u][0] = 0; f[u][1] = happy[u]; rep(i, 0, son[u].size() - 1) { 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。
代码实现如下:
rep(i, 0, n - 2) { int u, v; u = read(); v = read(); son[v].push_back(u); vis[u] = 1; } rep(i, 0, n - 1) if (!vis[i]) { root = i; break; } dp(root);