皇宫看守 树形DP + 状态机

皇宫看守 树形DP + 状态机_第1张图片
样例

样例输入
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
样例输出
25

思路
皇宫看守 树形DP + 状态机_第2张图片
代码

#include 
#include 
#include 

using namespace std;

const int N = 1510;
int e[N], w[N], h[N], len, ne[N];
int f[N][3];
int n;
bool vis[N];

void add(int a, int b)
{
     
    e[len] = b;
    ne[len] = h[a];
    h[a] = len++;
}

/*
0 父亲看见
1 孩子看见   f[k][2] + {min(f[y][1], f[y][2]);} == f[x][0]
2自己放一个

*/
void dfs(int x)
{
     
    f[x][2] = w[x];
    for(int i = h[x]; ~i; i = ne[i])
    {
     
        int y = e[i];
        dfs(y);
        
        f[x][0] += min(f[y][1], f[y][2]);
        f[x][2] += min(f[y][0], min(f[y][2], f[y][1]));
    }
    
    f[x][1] = 1e9;
    for(int i = h[x]; ~i; i = ne[i])
    {
     
        int y = e[i];
        f[x][1] = min(f[x][1], f[y][2] + f[x][0] - min(f[y][1], f[y][2]));
    }
}

int main()
{
     
    cin >> n;
    memset(h, -1, sizeof h);
    for(int i = 1; i <= n; i++)
    {
     
        int a;
        cin >> a;
        cin >> w[a];
        int t;
        cin >> t;
        for(int j = 1; j <= t; j++)
        {
     
            int b;
            cin >> b;
            add(a, b);
            vis[b] = true;
        }
    }
    
    int root = 0;
    for(int i = 1; i <= n; i++)
        if(!vis[i])
        {
     
            root = i;
            break;
        }
    dfs(root);
    cout << min(f[root][1], f[root][2]) << endl;
    return 0;
}

你可能感兴趣的:(动态规划)