解题报告 『没有上司的舞会 树状DP』

原题地址

很经典的一道树状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];
    }
}
View Code

不过在这之前需要先找到根结点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);
View Code

猜你喜欢

转载自www.cnblogs.com/Kirisame-Marisa/p/10292259.html