HDU - 1520 Anniversary party (树形dp)

There is going to be a party to celebrate the 80-th Anniversary of the Ural State University. The University has a hierarchical structure of employees. It means that the supervisor relation forms a tree rooted at the rector V. E. Tretyakov. In order to make the party funny for every one, the rector does not want both an employee and his or her immediate supervisor to be present. The personnel office has evaluated conviviality of each employee, so everyone has some number (rating) attached to him or her. Your task is to make a list of guests with the maximal possible sum of guests' conviviality ratings. 

Input

Employees are numbered from 1 to N. A first line of input contains a number N. 1 <= N <= 6 000. Each of the subsequent N lines contains the conviviality rating of the corresponding employee. Conviviality rating is an integer number in a range from -128 to 127. After that go T lines that describe a supervisor relation tree. Each line of the tree specification has the form: 
L K 
It means that the K-th employee is an immediate supervisor of the L-th employee. Input is ended with the line 
0 0

Output

Output should contain the maximal sum of guests' ratings. 

Sample Input

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

Sample Output

5

 

   上级下级不能同时出现,每个人出现有着自己独特的值,问让出现的人的值综合最大是多少。

   这道题一看到上级下级,就会有人要建立有向图,其实不然,上级下级之间有的只是不能共存着一个特点而已,并没有像树一样需要你严格从上往下遍历,所以建立无向图之后随便找一个作为根遍历就好,注意加一个vis数组防止存在环。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 20000;
struct fcuk {
	int u, v, ne;
}ed[maxn];
int n, head[maxn], cnt;
int v[maxn], dp[maxn][3], vis[maxn];
void init() {
	memset(dp, 0, sizeof(dp));
	memset(head, -1, sizeof(head));
	memset(vis, 0, sizeof(vis));
	cnt = 0;
}
void add(int u, int v) {
	ed[cnt].u = u; ed[cnt].v = v;
	ed[cnt].ne = head[u]; head[u] = cnt++;
}
void dfs(int x) {
	vis[x] = 1;
	dp[x][1] = v[x];
	for (int s = head[x]; ~s; s = ed[s].ne) {
		int v = ed[s].v;
		if (vis[v])continue;
		dfs(v);
		dp[x][0] += max(dp[v][1], dp[v][0]);
		dp[x][1] += dp[v][0];
	}
}
int main() {
	while (~scanf("%d", &n)) {
		init();
		for (int s = 1; s <= n; s++){
			scanf("%d", &v[s]);
		}
		int a, b;
		while (~scanf("%d%d", &a, &b) && a + b) {
			add(a, b); add(b, a);
		}
		dfs(1);
		int ans = max(dp[1][0], dp[1][1]);
		printf("%d\n", ans);
	}
}

 

全部评论

相关推荐

求好运眷顾🙏🏻:翻译:面试前没盘点好hc一下面太多了,现在在排序回去等通知
点赞 评论 收藏
分享
上周组里招人,我面了六个候选人,回来跟同事吃饭的时候聊起一个让我挺感慨的现象。前三个候选人,算法题写得都不错。第一道二分查找,五分钟之内给出解法,边界条件也处理得干净。第二道动态规划,状态转移方程写对了,空间复杂度也优化了一版。我翻他们的简历,力扣刷题量都在300以上。后三个呢,就有点参差不齐了。有的边界条件没处理好,有的直接说这道题没刷过能不能换个思路讲讲。其中有一个女生,我印象特别深——她拿到题之后没有马上写,而是先问我:“面试官,我能先跟你确认一下我对题目的理解吗?”然后她把自己的思路讲了一遍,虽然最后代码写得不是最优解,但整个沟通过程非常顺畅。这个女生的代码不是最优的,但当我问她“如果这里是线上环境,你会怎么设计’的时候,她给我讲了一套完整的方案——异常怎么处理、日志怎么打、怎么平滑发布。她对这是之前在实习的时候踩过的坑。”我在想LeetCode到底在筛选什么?我自己的经历可能有点代表性。我当年校招的时候,也是刷了三百多道题才敢去面试。那时候大家都刷,你不刷就过不了笔试关。后来工作了,前三年基本没再打开过力扣。真正干活的时候,没人让你写反转链表,也没人让你手撕红黑树。更多的是:这个接口为什么慢了、那个服务为什么OOM了、线上数据对不上了得排查一下。所以后来我当面试官,慢慢调整了自己的评判标准。算法题我还会出,但目的变了。我出算法题,不是想看你能不能背出最优解。而是想看你拿到一个陌生问题的时候,是怎么思考的。你会先理清题意吗?你会主动问边界条件吗?你想不出来的时候会怎么办?你写出来的代码,变量命名乱不乱、结构清不清楚?这些才是工作中真正用得到的能力。LeetCode是一个工具,不是目的。它帮你熟悉数据结构和常见算法思路,这没问题。但如果你刷了三百道题,却说不清楚自己的项目解决了什么问题、遇到了什么困难、你是怎么解决的,那这三百道题可能真的白刷了。所以还要不要刷LeetCode?要刷,但别只刷题。刷题的时候,多问自己几个为什么:为什么用这个数据结构?为什么这个解法比那个好?如果换个条件,解法还成立吗?把刷题当成锻炼思维的方式,而不是背答案的任务。毕竟面试官想看到的,从来不是一台背题机器,而是一个能解决问题的人。
牛客51274894...:意思是光刷力扣还不够卷
AI时代还有必要刷lee...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务