洛谷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 分算法十分雷同,但是我死在了考场的一线上……

posted @ 2018-11-15 00:50  等傻子仙女的傻子  阅读(133)  评论(0编辑  收藏  举报