节点选择 蓝桥杯

本文介绍蓝桥杯练习题中关于节点选择的动态规划解决方案。通过邻接表法记录边,状态转移方程涉及选择或不选择节点。文章探讨了邻接表法的理解,并分享了两份代码实现,最终给出AC代码,强调理解和优化的重要性。
摘要由CSDN通过智能技术生成

蓝桥杯练习题-节点选择

在这里插入图片描述
先说思路:很明显的动态规划问题,将每个顶点出发能选出的最大值记录下来就好,每个节点要么选,要么不选,所以状态转移方程为:
选择此节点:不选择全部子节点的总和
不选择此节点:对于每一个个子节点:选择子节点或不选择子节点的较大值 的总和。

细节:边的记录:边可以用邻接表法或者邻接矩阵法记录(此处选用邻接表法因为点有很多,邻接矩阵要用到很大的存储空间而边只有n-1个利用率不高),但是做这个题之前笔者并不了解邻接表法,看了一些攻略,暂且总结如下:
1.CSDN
2.B站
ps.由于CSDN大佬写的比较深奥,初看不太懂,才有了本文的诞生.
个人理解:邻接表的first[]数组和next[]数组是相互配合,构造next链表的同 时把每一个顶点的表头不断存更新在first[]数组中,每一次改变next[]数组的值就是在first[]数组中取得从顶点出发的边的编号,每一次改变first[]数组的值就是把最新的以下标顶点出发的边的编号记录下来.
看过B站的讲解之后,仿照编写此题代码如下:

#include<stdio.h>
#include<string.h>
#define MAX 100005
int d[MAX+1][2];
int first[MAX+1];//0好下标废弃不用,1-MAX以顶点作为下标
int next[2*(MAX-1)];//一条边分别以不同的顶点记录两次故乘二,next数组的下标是边的序号
int u[MAX],v[MAX];//记录每条边u-v
int max(int a,int b){
   
	return a>b? a:b;
}

void dp(int n,int pre){
   //n是当前节点,pre是父节点
	int k = first[n];
	d[n][0] = 0;
	while(k!=-1){
   
		if(v[k]!=pre){
   //防止死循环,从这个顶点出发就不该把这个顶点的权值算到子节点里去
			dp(v[k],n);//这条边的另一个顶点作为新的顶点,当前节点就自然是树的父节点
			d[n][
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值