蓝桥杯python每日刷题day 14

题目:

给定一棵树,树根为 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)注意事项:

标红部分为创建树和遍历树的每一层,是基础能力,以后要反复观看

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值