洛谷2016 战略游戏 (0/1状态的普通树形Dp)

题意:

给出一个树,覆盖树上某一个点的花费为w[i],求树上每一条边至少有一个点覆盖的最小花费。

细节:

1.一条边的两端可以均被覆盖,但是不能存在一条边的两端都不被覆盖。
2.可能存在

分析:

对于一对儿子和父亲节点来说,要么儿子覆盖父亲不覆盖,父亲覆盖儿子不覆盖,或者是两者均被覆盖,所以不难发现对于父亲节点来说,若其被覆盖,则它的所有子孙可以被覆盖也可以不被覆盖,若其不被覆盖,则它的子孙必须可以被全部覆盖。

所以状态变得显然:dp[u][0/1] 表示节点 u 是否被覆盖的最小花费
再根据上方的分析条件转移如下:
dp[u][1] = ∑ min( dp[v][0] , dp[v][1] )
dp[u][0] = ∑ dp[v][1]

代码

#include<bits/stdc++.h>
#define MAXN 1505
using namespace std;

int f[MAXN][2], n;
vector<int> Right[MAXN];

void dfs(int u, int fa){
    f[u][0]=0, f[u][1]=1;
    for (int i=0; i<Right[u].size(); i++) {
        int v=Right[u][i];
        if (v==fa) continue;
        dfs(v, u);
        f[u][0]+=f[v][1];
        f[u][1]+=min(f[v][0], f[v][1]);
    }
}

int main(){
    scanf("%d", &n);
    for (int i=1, x, num; i<=n; i++) {
        scanf("%d%d", &x, &num);
        for (int j=1, y; j<=num; j++) {
            scanf("%d", &y);
            Right[x].push_back(y);
            Right[y].push_back(x);
        }
    }
    dfs(1, -1);
    printf("%d\n", min(f[root][0], f[root][1]));
    return 0;
}

Ps:

此题与 DAY2T344 分算法十分雷同,但是我死在了考场的一线上……

猜你喜欢

转载自www.cnblogs.com/xiannvzuimei/p/9961319.html