chenfy27的刷题记录

导航

luoguP1352 没有上司的舞会

给定一棵有N个节点的树,节点i的权值为r[i],需要选出一些不相邻的节点,使得权值之和最大,求最大值。
1<=N<=6E3; -128<=r[i]<=127

分析:自下而上dp,对于每个节点,可以选或者不选。如果选,那么其子节点不能选;如果不选,那么其子节点可以选或不选。

#include <bits/stdc++.h>
using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::vector<int> r(n);
	for (int i = 0; i < n; i++) {
		std::cin >> r[i];
	}
	std::vector<int> fa(n, -1);
	std::vector<std::vector<int>> adj(n);
	for (int i = 1; i < n; i++) {
		int x, y;
		std::cin >> x >> y;
		x--, y--;
		fa[x] = y;
		adj[y].push_back(x);
	}
	int root = -1;
	for (int i = 0; i < n; i++) {
		if (fa[i] == -1) {
			root = i;
			break;
		}
	}

	std::vector<std::array<int,2>> dp(n);

	auto dfs = [&](auto self, int x) -> void {
		dp[x][0] = 0;
		dp[x][1] = r[x];
		for (auto i : adj[x]) {
			self(self, i);
			dp[x][0] += std::max(dp[i][0], dp[i][1]);
			dp[x][1] += dp[i][0];
		}
	};

	dfs(dfs, root);
	std::cout << std::max(dp[root][0], dp[root][1]) << "\n";
}

int main() {
	std::cin.tie(0)->sync_with_stdio(0);
	int t = 1;
	while (t--) solve();
	return 0;
}

posted on 2024-11-03 15:19  chenfy27  阅读(2)  评论(0编辑  收藏  举报