题解【洛谷P1352】没有上司的舞会

题面

题解

树形\(\text{DP}\)入门题。

我们设\(dp[i][0/1]\)表示第\(i\)个节点选\(/\)不选的最大快乐指数。

状态转移方程:
\(dp[i][0]=a[i]+\sum_{v∈son[u]}dp[v][1]\),其中\(a[i]\)为每个员工的快乐指数。
\(dp[i][1]=\sum_{v∈son[u]}\max{(dp[v][1],dp[v][0])}\)

答案为\(\max{(dp[rt][0],dp[rt][1])}\),其中\(rt\)为没有上司的员工。

转移一下即可。

代码

#include <bits/stdc++.h>
#define itn int
#define gI gi

using namespace std;

inline int gi()
{
	int f = 1, x = 0; char c = getchar();
	while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
	while (c >= '0' && c <= '9') x = x * 10 + (c ^ 48), c = getchar();
	return f * x;
}

const int maxn = 6003;

int n, a[maxn], tot, head[maxn], ver[maxn * 2], nxt[maxn], ans, vis[maxn], rt;
int dp[maxn][2];//0:xuan 1:buxuan

inline void add(int u, int v)
{
	ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}

void dfs(int u, int f)
{
	dp[u][0] = a[u];
	for (int i = head[u]; i; i = nxt[i])
	{
		int v = ver[i];
		if (v == f) continue;
		dfs(v, u);
		dp[u][0] += dp[v][1];
		dp[u][1] += max(dp[v][0], dp[v][1]);//状态转移
	}
}

int main()
{
	n = gi();
	for (int i = 1; i <= n; i+=1) a[i] = gi();
	for (int i = 1; i < n; i+=1)
	{
		int u = gi(), v = gi();
		add(u, v);
		add(v, u);
		vis[u] = 1;
	}
	int h = gi(), o = gi();
	for (int i = 1; i <= n; i+=1) if (!vis[i]) {rt = i; break;}//找到根节点,即没有上司的员工编号
	dfs(rt, 0);
	printf("%d\n", max(dp[rt][0], dp[rt][1]));//答案就是根节点选/不选取max
	return 0;
}

总结

由此,我们可以得出树形\(\text{DP}\)的状态的基本形式:

\(dp[i][…]\)表示第\(i\)个节点的状态。

posted @ 2019-11-09 16:59  csxsi  阅读(159)  评论(0编辑  收藏  举报