• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

HDU 1520 树形DP入门

HDU 1520

【题目链接】HDU 1520

【题目类型】树形DP

&题意:

某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大。

&题解:

poj有一个一样的题,被那个坑了,看的是那个的代码,之后提交hdu总是超时,最后发现递归的时候总是循环n遍,所以才超的时。
只要存下每个节点的孩子就好了,但father数组还是要用的,因为要用它来求根是哪个。(或许也可以不用,但是我没想到)

&代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <algorithm>
#define cle(a,v) memset(a,(v),sizeof(a))
#define ll long long
const int maxn = 6000 + 7;
int n, dp[maxn][2], father[maxn], u, v;
bool vis[maxn];
std::vector<int> ch[maxn];
void tree_dp(int u) {
	vis[u] = 1;
	for (int i = 0; i < ch[u].size(); i++) {
		if (!vis[ch[u][i]] && father[ch[u][i]] == u) {
			tree_dp(ch[u][i]);
			dp[u][1] += dp[ch[u][i]][0];
			dp[u][0] += std::max(dp[ch[u][i]][1], dp[ch[u][i]][0]);
		}
	}
}
int main() {
	freopen("1.in", "r", stdin);
	while (~scanf("%d", &n)) {
		for (int i = 1; i <= n; i++)
			ch[i].clear();
		memset(father, -1, sizeof(father));
		memset(vis, 0, sizeof(vis));
		memset(dp, 0, sizeof(dp));
		for (int i = 1; i <= n; i++) {
			scanf("%d", &dp[i][1]);
		}
		int root = 1;
		while (scanf("%d%d", &u, &v), u || v) {
			father[u] = v;
			ch[v].push_back(u);
		}
		while (father[root] != -1) root = father[root];
		// printf("%d\n", root);
		tree_dp(root);
		printf("%d\n", std::max(dp[root][1], dp[root][0]));
	}
	return 0;
}
posted @ 2017-07-30 17:29  s1124yy  阅读(189)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3