题目:
给定一棵树,树根为 1,每个点的点权为 Vi 。
你需要找出若干个点 Pi,使得:
1. 每两个点 Px Py 互不相邻;
2. 每两个点 Px Py 与树根的距离互不相同;
3. 找出的点的点权之和尽可能大。
请输出找到的这些点的点权和的最大值。
输入格式
输入的第一行包含一个整数 n 。
第二行包含 n − 1 个整数 Fi ,相邻整数之间使用一个空格分隔,分别表示 第 2 至 n 个结点的父结点编号。
第三行包含 n 个整数 Vi,相邻整数之间使用一个空格分隔,分别表示每个结点的点权。
输出格式
输出一行包含一个整数表示答案。
(1)代码:
n = int(input()) L = [[-1, 0] for i in range(n + 1)] # 存储每个结点的【双亲编号,权】 L2 = list(map(int, input().split())) j = 2 for i in range(len(L2)): L[j][0] = L2[i] # 父节点 j += 1 因为l2中的第i个元素为树中第二个元素的父节点 L3 = list(map(int, input().split())) j = 1 for i in range(len(L3)): L[j][1] = L3[i] # 结点权值 j += 1 # 找到每一层的结点 # 有多少层呢?最多n层 layer_node = [[] for i in range(n + 1)] layer_node[1] = [1] for i in range(2, n + 1): h = 2 j = i while L[j][0] != 1: h += 1 j = L[j][0] 因为书的根节点为1,将j每一次变为他的父节点,直到j的父节点为根节点,期间h一直再叠加,就可以知道i是第几层的了 layer_node[h].append(i) for i in range(1, n + 1): if layer_node[i] == []: break 当break时,此时(i-1)为层数
dp=[[-1,-1] for i in range(n+1)]
#dp[i][0]存储从根层到结点i,不选取i时,已有序列的最大值
#dp[i][1]存储从根层到结点i,选取i时,已有序列的最大值
#这样从前到后推,最后一层中保存的最大值才是最终要找的
dp[1] = [0, L[1][1]] for x in range(2, i): dp0max = -1 dp1max1 = dp1max2 = [-1, -1] if len(layer_node[x - 1]) > 1: for j in layer_node[x - 1]: if dp[j][1] > dp1max1[1]: dp1max2 = dp1max1 dp1max1 = [j, dp[j][1]] elif dp[j][1] > dp1max2[1]: dp1max2 = [j, dp[j][1]] if dp[j][0] > dp0max: dp0max = dp[j][0] else: j = layer_node[x - 1][0] dp1max1 = [j, dp[j][1]] dp1max2 = [j, 0] dp0max = dp[j][0] for k in layer_node[x]: dp[k][0] = max(dp0max, dp1max1[1]) dp[k][1] = max(dp0max, dp1max1[1]) + L[k][1] j = dp1max1[0] if L[k][0] == j: # j是k的双亲节点 dp[k][1] = max(dp0max, dp1max2[1]) + L[k][1] 用第二大的值是因为,题意要求两个节点不能相连 ans = 0 for j in layer_node[i- 1]: 此处不用[-1]是因为layer_node被创造了n层,但有数的层数没达到n层,按照上一个循环,i-1为层数 ans = max(ans, dp[j][0], dp[j][1]) print(ans) """**dp0max**:上一层节点中不选择任何节点时的最大点权和。 **dp1max1**:上一层节点中选择一个节点时的最大点权和及其对应的节点。 **dp1max2**:上一层节点中选择一个节点时的次大点权和及其对应的节点。"""
(2)解析:
先根据题目所给的要求,如第二行为每个节点的父节点,据此来构建树,并创建一个列表来储存每一节点的父节点和权值,接下来来获取树每一层的节点
(3)注意事项:
标红部分为创建树和遍历树的每一层,是基础能力,以后要反复观看