蓝桥杯结点选择(树形动态规划)

蓝桥杯 算法训练 结点选择 题目 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输入 5 1 2 3 4 5 1 2 1 3 2 4 2 5 样例输出 12 样例说明 选择3、4、5号点,权值和为 3+4+5 = 阅读详情

这道题就是一道树的最大独立集问题。先看一下题目要求:

问题描述
有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少?


输入格式
第一行包含一个整数 n 。


接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。


接下来一共 n-1 行,每行描述树上的一条边。


输出格式
输出一个整数,代表选出的点的权值和的最大值。
样例输入
5
1 2 3 4 5
1 2
1 3
2 4
2 5
样例输出
12
样例说明
选择3、4、5号点,权值和为 3+4+5 = 12 。
数据规模与约定
对于20%的数据, n <= 20。


对于50%的数据, n <= 1000。


对于100%的数据, n <= 100000。


权值均为不超过1000的正整数。


好的那么我们看一下解决思路:

首先一定是要接收输入的值,

再者就是把结点相连,构建成树。

题目告诉不一定是二叉树,所以可以看做图来处理

可以使用邻接表存储建立一个数组tree[i][j]表示结点i的第j个孩子结点

dp[i][0]表示不取i结点的结果

dp[i][1]表示取i结点的结果

用深度优先搜索和动态规划,每个点的最大权值有两种情况,取和不取该结点,如果取了这个结点,哪么与它相邻的点就不能取了;不取当前点则取与他相邻点的最大值进行累加,从底向上累加到顶部:max(dp[i][1],dp[i][0])就是要求的结果。

用一个变量root保存当前结点的前一个结点,如果等于了root说明访问到了它的父亲结点,为了防止重复访问,要在tree[start][i]不等于root时候继续dfs下去,否则,可能成为无限循环的环。

思路就是这样,让我们一起撸代码吧!

import java.util.Scanner;

public class Main {
    public int[][] dp = new int[100002][2];   
    public int[][] tree = new int[100002][300];  //tree[i][3] = num表示第i个节点的第3个孩子节点为第num个节点
    /*
     * 参数point1:表示输入的第point1个节点,不是节点权值
     * 参数point2:表示输入的第point2的节点,不是节点权值
     * 采用邻接表来存储数据的值。
     */
    public void creatTree(int point1, int point2) {
        int i = 0;
        //当第point1个节点为父母节点时
        while(tree[point1][i] != 0) i++;  //如果第point1个节点已经有孩子了,再增加一个孩子  
        tree[point1][i] = point2;
        int j = 0;
        //当第point2个节点为父母节点时
        while(tree[point2][j] != 0) j++;
        tree[point2][j] = point1;
    }
    /*
     * 参数satrt:开始对树进行DFS遍历的开始节点,为具体节点位置,不是节点权值
     * 参数root:为第start个节点的直接父母节点位置,root = 0表示根节点的父母节点
     */
    public void dfs(int start, int root) {
        int child = tree[start][0];  //第start个节点的第1个孩子节点
        for(int i = 0;child != 0;i++) {
            child = tree[start][i];
            if(child != root) {  //防止出现start的孩子成为start的父亲情况
                dfs(child, start);
                dp[start][1] += dp[child][0]; 
                dp[start][0] += (dp[child][1] > dp[child][0] ? dp[child][1] : dp[child][0]);
            }
        }
    }
    
    public static void main(String[] args) {
        Main test = new Main();
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        for(int i = 0;i < n;i++)
            test.dp[i + 1][1] = in.nextInt();
        for(int i = 0;i < n - 1;i++) {
            int point1 = in.nextInt();
            int point2 = in.nextInt();
            test.creatTree(point1, point2);
        }
        test.dfs(1, 0);   //从创建的数的根节点(即第1个顶点,0表示根节点的父母节点)开始进行DFS遍历
        int max = (test.dp[1][1] > test.dp[1][0] ? test.dp[1][1] : test.dp[1][0]);
        System.out.println(max);
    }
}

从运行结果来看,这道题是正确的。

但是提交之后,是超时的只得了50分,所以,还需要改进。

搜索了一下超时的原因:说是Scanner效率太低,所以使用了BufferedReader+StringTokenizer的方法依然超时。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {
    public int[][] dp = new int[100002][2];   
    public int[][] tree = new int[100002][300];  //tree[i][3] = num表示第i个节点的第3个孩子节点为第num个节点
    /*
     * 参数point1:表示输入的第point1个节点,不是节点权值
     * 参数point2:表示输入的第point2的节点,不是节点权值
     * 说明:由于题目仅仅给出边的说明,并未说明两个节点谁是父母节点,所以以下有两种情形
     */
    public void creatTree(int point1, int point2) {
        int i = 0;
        //当第point1个节点为父母节点时
        while(tree[point1][i] != 0) i++;  //如果第point1个节点已经有孩子了,再增加一个孩子  
        tree[point1][i] = point2;
        int j = 0;
        //当第point2个节点为父母节点时
        while(tree[point2][j] != 0) j++;
        tree[point2][j] = point1;
    }
    /*
     * 参数satrt:开始对树进行DFS遍历的开始节点,为具体节点位置,不是节点权值
     * 参数root:为第start个节点的直接父母节点位置,root = 0表示根节点的父母节点
     */
    public void dfs(int start, int root) {
        int child = tree[start][0];  //第start个节点的第1个孩子节点
        for(int i = 0;child != 0;i++) {
            child = tree[start][i];
            if(child != root) {  //防止出现start的孩子成为start的父亲情况
                dfs(child, start);
                dp[start][1] += dp[child][0];  
                dp[start][0] += (dp[child][1] > dp[child][0] ? dp[child][1] : dp[child][0]);
            }
        }
    }
    
    public static void main(String[] args) throws IOException {
        Main test = new Main();
        //Scanner in = new Scanner(System.in);
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        
        String input=reader.readLine();
        int n =	Integer.parseInt(input);
        String input1=reader.readLine();
        StringTokenizer tok0=new StringTokenizer(input1);
        for(int i = 0;i < n;i++) {
            test.dp[i + 1][1] = Integer.valueOf(tok0.nextToken());
        }
        for(int i = 0;i < n - 1;i++) {
        	String input2=reader.readLine();
        	StringTokenizer tok=new StringTokenizer(input2);
            int point1=Integer.valueOf(tok.nextToken());
            int point2=Integer.valueOf(tok.nextToken());
            test.creatTree(point1, point2);
        }
        test.dfs(1, 0);   //从创建的数的根节点(即第1个顶点,0表示根节点的父母节点)开始进行DFS遍历
        int max = (test.dp[1][1] > test.dp[1][0] ? test.dp[1][1] : test.dp[1][0]);
        System.out.println(max);
    }
}
在网上找到一个AC了的代码,分析一下代码的缺陷在哪,
import java.io.*;
import java.util.*;

public class Main {
	
	final static int MAX_N = 100010;

	PrintWriter out;
	InputReader cin;
	int edgecnt;
	int dp[][] = new int[MAX_N][2];
	Edge E[] = new Edge[MAX_N * 2];
	int head[] = new int[MAX_N];
	int sta[] = new int[MAX_N * 2];
	boolean vis[] = new boolean[MAX_N];
	
	class Edge {
		int u, v, nxt;
		Edge () {
			
		}
		Edge (int _u, int _v, int _n) {
			u = _u;
			v = _v;
			nxt = _n;
		}
	}
	class InputReader {
		InputReader(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
			tokenizer = new StringTokenizer("");
		}

		private String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		public Integer nextInt() throws IOException {
			return Integer.parseInt(next());
		}
		private BufferedReader reader;
		private StringTokenizer tokenizer;
	}

	
	void add(int u, int v) {
		E[edgecnt] = new Edge(u, v, head[u]);
		head[u] = edgecnt++;
	}
	
	void dfs(int x, int fa) {
		Arrays.fill(vis, false);
		int top = 0;
		vis[x] = true;
		sta[top++] = x;
		while (top > 0) {
			int u = sta[top - 1];
			boolean Ed = false;
			for (int i = head[u]; i + 1 != 0; i = E[i].nxt) {
				int v = E[i].v;
				if (vis[v]) continue;
				Ed = true;
				sta[top++] = v;
				vis[v] = true;
			}
			if (Ed) continue;
			--top;
			for (int i = head[u]; i + 1 != 0; i = E[i].nxt) {
				int v = E[i].v;
				dp[v][0] += Math.max(dp[u][0], dp[u][1]);
				dp[v][1] += dp[u][0];
				
			}
		}
	}
	
	void run() throws IOException {
		int n = cin.nextInt();
		
		for (int i = 1; i <= n; ++i) 
			dp[i][1] = cin.nextInt();
		Arrays.fill(head, -1);
		for (int i = 1; i < n; ++i) {
			int u = cin.nextInt();
			int v = cin.nextInt();
			add(u, v);
			add(v, u);
		}
		dfs(1, -1);
		int ans = Math.max(dp[1][0], dp[1][1]);
		out.println(ans);
		out.close(); 
	}

	public static void main(String[] args) throws IOException {
		new Main().run();
	}

	Main() {
		cin = new InputReader(System.in);
		out = new PrintWriter(System.out);
	}

}
这是别人写的代码让我们看一下问题。

将代码改写成下面这样依然不行,说明在思路上除了问题

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

public class Main {
    public  int[][] dp = new int[100002][2];   
    public int[][] tree = new int[100002][300];  //tree[i][3] = num表示第i个节点的第3个孩子节点为第num个节点
    PrintWriter out;
    InputReader cin;
    /*
     * 参数point1:表示输入的第point1个节点,不是节点权值
     * 参数point2:表示输入的第point2的节点,不是节点权值
     * 说明:由于题目仅仅给出边的说明,并未说明两个节点谁是父母节点,所以以下有两种情形
     */
    public void creatTree(int point1, int point2) {
        int i = 0;
        //当第point1个节点为父母节点时
        while(tree[point1][i] != 0) i++;  //如果第point1个节点已经有孩子了,再增加一个孩子  
        tree[point1][i] = point2;
        int j = 0;
        //当第point2个节点为父母节点时
        while(tree[point2][j] != 0) j++;
        tree[point2][j] = point1;
    }
    /*
     * 参数satrt:开始对树进行DFS遍历的开始节点,为具体节点位置,不是节点权值
     * 参数root:为第start个节点的直接父母节点位置,root = 0表示根节点的父母节点
     */
    public void dfs(int start, int root) {
        int child = tree[start][0];  //第start个节点的第1个孩子节点
        for(int i = 0;child != 0;i++) {
            child = tree[start][i];
            if(child != root) {  //防止出现start的孩子成为start的父亲情况
                dfs(child, start);
                dp[start][1] += dp[child][0];  
                dp[start][0] += Math.max(dp[child][1], dp[child][0]);
            }
        }
    }
    void run() throws IOException {
    	 int n =	cin.nextInt();
         for(int i = 0;i < n;i++) {
             dp[i + 1][1] = cin.nextInt();
         }
         for(int i = 0;i < n - 1;i++) {
             int point1=cin.nextInt();
             int point2=cin.nextInt();
             creatTree(point1, point2);
         }
         dfs(1, 0);   //从创建的数的根节点(即第1个顶点,0表示根节点的父母节点)开始进行DFS遍历
         int max = Math.max(dp[1][1], dp[1][0]);
         out.println(max);
         out.close();
	}
    public static void main(String[] args) throws IOException {
    	new Main().run();
    }
    
    Main() {
		 cin = new InputReader(System.in);
		 out = new PrintWriter(System.out);
	}

	class InputReader {
		InputReader(InputStream in) {
			reader = new BufferedReader(new InputStreamReader(in));
			tokenizer = new StringTokenizer("");
		}

		private String next() throws IOException {
			while (!tokenizer.hasMoreTokens()) {
				tokenizer = new StringTokenizer(reader.readLine());
			}
			return tokenizer.nextToken();
		}

		public Integer nextInt() throws IOException {
			return Integer.parseInt(next());
		}
		private BufferedReader reader;
		private StringTokenizer tokenizer;
	}
}

路过的大神,帮帮忙!

SecureCRT多种配色方案配置文件 位置 C:\Users%USERNAME%\AppData\Roaming\VanDyke\Config\Global.ini S:"SecureCRT Tab State"=1,1,1,0,0 S:"SecureFX Local Tab State"=1,-1,200 D:"Max Chat Window History"=000000c8 D:"Active Window Alpha Transparency"=000000f0 D:"Save Keymaps As Unicode"=00000000 阅读详情

相关推荐

Multisim仿真运放积分器踩坑实录:为什么你的方波变不成三角波?

本文针对Multisim仿真运放积分器时方波无法转换为三角波的常见问题,提供了详细的排查与调试指南。文章指出,经典RC积分电路因直流反馈开路导致运放饱和,核心解决方案是在反馈电容两端并联大阻值电阻以稳定直流工作点。通过参数优化(调整Rin、C、Rf)和高级仿真技巧,手把手教你调出线性度好、幅度适中的完美三角波,并分享异常波形(如饱和、不对称、振荡)的对应策略。

weixin_29231263的博客 114

第十四届蓝桥杯模拟赛c++ 试题 I

第十四届蓝桥杯模拟赛

qq_39940634的博客 2545

Overleaf-Latex-Elsevier-图、表、参考文献标题及引用、伪代码写法(绝对详细直观且易懂)

overleaf爱思唯尔模板踩过的一些坑以及解决办法

2403_87584552的博客 5851

算法训练 结点选择

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输入 ...

菲菲家的吴先森 2370

拆解大疆M300电池BMS:基于TI TIDA-010030方案的硬件架构深度分析

本文深度解析了大疆M300无人机电池管理系统(BMS)基于TI TIDA-010030参考设计的硬件架构。通过对比TI方案与大疆实现的差异,详细介绍了BQ7694003监控前端和BQ34Z100电量计的优化设计,以及通信架构的可靠性改进。文章还揭示了大疆在成本、空间和标准化方面的工程妥协与创新平衡,为锂电池保护方案提供了实践参考。

weixin_27066963的博客 237

2024 全国大学生新质生产力大赛 B:金融违规交易的大数据分析 问题四思路代码

问题四:请分析附件中所有的指标数据,选取合适的指标,建立“金融违规 洗钱交易的预测模型”,并选取合适的训练集和测试集,计算预测模型的准确率。 为了提前识别并预测金融违规洗钱的交易事件,请基于你们团队数据分析的结果, 分别给公安部门和银行机构提出你们的建议。

YOLO 375

节点选择(树形动态规划)

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输入 5 ......

Cactus_Lrg的博客 1828

linux驱动由浅入深系列:块设备驱动之一(高通eMMC分区实例)

linux驱动由浅入深系列:块设备驱动之一(高通eMMC分区实例)linux驱动由浅入深系列:块设备驱动之二(块设备驱动结构分析)块设备驱动的模型还是基本基于字符设备驱动的,可以简单理解为块设备仅仅增加了操作缓冲区,对用户请求顺序进行队列重拍等等。字符设备驱动的相关分析可以查看本博客相关的博文。 按照本博客的行文习惯,在具体分析块设备驱动代码之前,我们会从整体上了解一下研究对象的特征,以及用户空间...

Radia的专栏 1万+

蓝桥杯2023年真题 python B组

Python 大学 B 组。

qq_62029644的博客 9520

地图自定义编码CSV转换成ini文件

创 建 schema.ini 文件:有时,当您尝试使用 .csv 文件将自定义地理信息导入 Tableau 时,您可能会看到“无法使用.csv,因为它不包含唯一列”错误消息。这是因为您的 .csv 文件可能包含数值数据,例如数值邮政编码。对于新的地理角色,Tableau 将只接受文本字段。但是,您可以创建一个 schema.ini 文件,以指示 Tableau 应将您要导入的数值字段视为文本字段。...

wenyusuran的专栏 1975

Vue3 - 手机移动端H5网页强力解决弹起软键盘后页面被挤压变形或页面整体上移问题,点击input输入框键盘弹出底部被上推往上顶遮挡及各种问题(兼容安卓苹果ios手机,微信公众号网页微信内置浏览器)

vue3,h5网页,input输入框组件,vue3 h5软键盘弹出,vue3输入框,键盘弹起时页面整体上移问题,uni,H5页面,解决软键盘弹起页面被挤压、被往顶的问题,解决vue3输入框,键盘弹起时页面整体上移问题,vue3调用手机系统软键盘,页面窗口被顶起,布局定位失效,解决VUE3软键盘弹起导致页面fixed定位元素被顶上去,输入法软键盘弹起,窗口顶起,变形解决办法,Vue中input组件在IOS设备上弹出软键盘时页面整体上移问题的解决方案,以及input组件聚焦后弹出软键盘固定在,Vue3软键盘把界

🏆 前端领域优质创作者 1万+

蓝桥杯算法训练 结点选择(树形动态规划 C语言)

结点选择 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输入 5 1 2 3...

hys__handsome的博客 1188

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

蓝桥杯 算法训练(四)结点选择(树形动态规划)C语言

结点选择(树形动态规划)C语言 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样...

qq_39913187的博客 1504

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

蓝桥杯--结点选择(树形动态规划)

蓝桥杯–结点选择(python,树形动态规划) 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输入 5 1 2 3 4 5 1 2 1 3 2 4 2 5 样例输出 12 样例说明 选择3

BlingBlingBlingd的博客 809

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

蓝桥杯-结点选择 (树形动态规划)

题目大意:给定一棵树,每个结点存储一个权值,从树中选择某些结点,使得总的权值最大。在选择结点时,有一个要求:当选定一个结点时,与该结点相连接的结点就不能选取。题目分析:方法:深度搜索+树形动态规划。对于每个点,有两个选择,分别是选和不选。对于第i个结点,我们用dp[i][0]表示不取该结点,所能达到的最大值;dp[i][1]表示取该结点,该结点所能达到的最大值。第一种情况,当我不取第i个结点,当前...

Jaster_wisdom的专栏 2045

蓝桥杯 算法训练 结点选择 (树形动态规划)

//蓝桥杯 算法训练 结点选择 (树形动态规划) #include #include #include using namespace std; const int N=100010; int n; int s[N]; int dp[N][2]={0}; int visit[N]={0}; vector node[N]; int Max(int a,int b) { if(a>b)

u014068781的专栏 892

蓝桥杯--结点选择

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 解题思路: 这题模型是树形动态规划入门题目, dp[i][0]表示该节点不被选择,dp[i][1]表示该结点被选择。 转移方程为: dp[u][1]+=dp[v][0];//选择了u结点,则与它邻接的结点不

微不足道 2399

树形动态规划练习《蓝桥杯 结点选择》

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输入 5 ...

weixin_30646315的博客 369

蓝桥杯 算法训练(四)结点选择(树形动态规划)

结点选择(树形动态规划)C语言 问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。...

weixin_40975029的博客 1089

结点选择 (蓝桥杯 树形动态规划)

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样...

weixin_34123613的博客 463

蓝桥杯 算法训练 结点选择 树形动态规划

简而言之,就是利用了广度优先搜索的思想 #include #include #include using namespace std; #define MAX 100010 int head[MAX]; int f[MAX][2]; int cur=0; //v是u相连的另一点,next为与u相连的另一条边上一条边 struct node{ int v,next; }

lnlnlnying的博客 544

蓝桥杯 算法训练 结点选择 (树形动态规划)

问题描述 有一棵 n 个节点的树,树上每个节点都有一个正整数权值。如果一个点被选择了,那么在树上和它相邻的点都不能被选择。求选出的点的权值和最大是多少? 输入格式 第一行包含一个整数 n 。 接下来的一行包含 n 个正整数,第 i 个正整数代表点 i 的权值。 接下来一共 n-1 行,每行描述树上的一条边。 输出格式 输出一个整数,代表选出的点的权值和的最大值。 样例输...

so_so_y的博客 607

蓝桥杯 · 算法训练 · 结点选择—树形dp

不恰当的思路 首先拿到题,就想到 图染色——蓝桥杯 · 分考场,dfs 从第一个节点遍历到第n个节点,对于每一个节点试着去装进一个room(一个room内的所有人都没有直接关系),最后接收 room 内所有节点的权值和。事实证明,不仅空间耗费大,时间复杂度也很大(因为要便利每一种对于每一个节点装与不装的组合),拿下10分。 AC思路 又联想到另一道题蓝桥杯 · 对局匹配,这个思...

qq_38125728的博客 440

蓝桥杯 ALGO-4 结点选择(树形动态规划)

初学动态规划,然后自己试着做了这一道题 ,发现思路完全错误……于是就花了好几个小时百度,终于对这道题有了一点理解!!!下面是思路: 定义一个二维数组dp,dp[i][0]表示结点i不被选择时 , i点及其子树能选出的最大权值;dp[i][1]表示结点选择i时,i点及其子树能选出的最大权值。 对于叶子结点dp[i][0] = 0 ; dp[i][1] = i(也可以说是此时数组所存的权值);

风花@小绳的博客 414

蓝桥杯:JAVA结点选择(树形动态规划)

private static int dp[][] = new int[10002][2]; private static int tree[][] = new int[10002][300]; //构建树 public static void createTree(int parent,int child){ int i = 0; while (tree[parent][i]!...

一点博客 1314
上一篇: 树形动态规划之树的最大独立集
下一篇: PHP学习入门之语法基础
Round_Yuan
博客等级 码龄10年 26粉丝 78原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值