蓝桥杯节点选择(java)第一道树形dp分析

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

蓝桥杯 节点选择



问题描述


有一棵 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的正整数。


分析



看到蓝桥杯的树形dp题,刚开始看的很蒙蔽。从来没做过树形的dp,刚开始表示很难理解,当时主要的疑惑点有一下几点:


1:这个树怎么解决?这么乱的一棵树感觉根本无法下手,因为你不知道那个是根节点,那个是子节点。输出的结果又和那个有关系?


2:树形怎么dp?以前都是遇到线性区间的dp,树形dp,怎么查找连续点,就算找到连续的点交叉点如何处理?


看了一些博客和文章之后,有了解到dp处理树形的特殊手段:


一: 一般来说,树形dp的每个节点都有一个选择性,本题就是该店选择和不选择,dp[i][0]表示不选择,dp[i][1]表示选择该节点。


二:对于树形dp,一般要和搜索结合(更确切的说是递归)结合,对于树的划分层次,一般是选择一个点,然后从这个点进行往下搜索 ,他的邻居都变成他的子节点。也就是相当于从这个根节点除法,可能有很多分叉。也就是有很多分叉会到根节点。但是这有和dp有啥关系呢?dp是从尾到头还是从头到尾?


三:对于顺序的选择肯定是从尾部到顶部,因为dp要的是一个整合结果而不是分散求最值或者其他。那么还有问题就是那么多的跟节点,那么多合的点,还有反向路径不好记录,记录的难度和开销都超级大。如果从尾部推到dp还是有一定难度。


四:我们要先抛开整体看局部这个点,对于某个单点来说(如果他是头节点),分析到他的结果,如果取他那么他的儿子们都不能取,那么dp[i][1]=dp[儿子们][0] value[i];如果不取他,那么对于每个儿子来说要给最大的,那么dp[i][0]=max(dp[每个儿子][0],dp[每个儿子][1]);这样就得到递推式dp[x][0]=sum(max(dp[num][0],dp[num][1]));dp[x][1]=sum(dp[num][0]) value[i].


五:对于头节点(可以任选),满足④,对于头节点的儿子也同样满足④,但是唯一不同的是要过滤头节点(准确的说是父节点)。防止死循环。递归搜索的过程是双向的过程,先去再回,我们可以同过先去构造树并且获得后面的一些信息,然后根据后来得到的值进行操作当前等级的dp。


总的来说这个树形dp就是分析某个点的状态方程,通过递归搜索进行划分树。获得结果。并且这题只有n-1条路径,n个点,不用考虑去重。


附上代码:


package 算法训练;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.List;
public class 节点选择 {
    // static boolean jud[];
     static int dp[][];//dp数组
     static int value[];//保存权值
     static List <Integer>[]list;//邻接表储存图。节省空间
  public static void main(String[] args) throws IOException {
    // TODO 自动生成的方法存根
    StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    in.nextToken();
    int n=(int)in.nval;
    value=new int[n];//权值
    dp=new int[n][2];
    list=new ArrayList[n];
    for(int i=0;i<n;i++) {list[i]=new ArrayList<>();}
    for(int i=0;i<n;i++)
    {
      in.nextToken();
      value[i]=(int)in.nval;
    }
    for(int i=0;i<n-1;i++)
    {
       in.nextToken();  int t1=(int)in.nval;
      in.nextToken();int t2=(int)in.nval;
      list[t1-1].add(t2-1);//添加路径
      list[t2-1].add(t1-1);     
    }
    dfs(0,-1);//理论上任意n之内节点都可以,但是右侧第一个理论上保证不是这个点的父亲
    int value=max(dp[0][0], dp[0][1]);
    out.println(value);
    out.flush();
  }
  private static void dfs(int x, int y) {//当前节点,父亲节点
    for(int i=0;i<list[x].size();i++)
    {
      int num=list[x].get(i);
      if(num!=y)//不是父亲节点
      {
        dfs(num,x);
        dp[x][0]+=max(dp[num][0],dp[num][1]);
        dp[x][1]+=dp[num][0];
      }
    }
    dp[x][1]+=value[x];//加上自己的权值
  }
  private static int max(int i, int j) {
    // TODO 自动生成的方法存根
    return i>=j?i:j;
  }
}


但是结果只能过7个,


2018110121485733.png


看了下其他人没优化输入的只能过5个超时。我用测试数据测试了一下原因是栈内存溢出。苦逼的Java。。


20181101215006741.png


也可能是因为我比较菜,,想不出好的方法,呵呵,。欢迎大佬踢场。。


目录
相关文章
|
4月前
|
缓存 JavaScript Java
常见java OOM异常分析排查思路分析
Java虚拟机(JVM)遇到内存不足时会抛出OutOfMemoryError(OOM)异常。常见OOM情况包括:1) **Java堆空间不足**:大量对象未被及时回收或内存泄漏;2) **线程栈空间不足**:递归过深或大量线程创建;3) **方法区溢出**:类信息过多,如CGLib代理类生成过多;4) **本机内存不足**:JNI调用消耗大量内存;5) **GC造成的内存不足**:频繁GC但效果不佳。解决方法包括调整JVM参数(如-Xmx、-Xss)、优化代码及使用高效垃圾回收器。
203 15
常见java OOM异常分析排查思路分析
|
3月前
|
存储 Java
【编程基础知识】 分析学生成绩:用Java二维数组存储与输出
本文介绍如何使用Java二维数组存储和处理多个学生的各科成绩,包括成绩的输入、存储及格式化输出,适合初学者实践Java基础知识。
102 1
|
23天前
|
缓存 算法 搜索推荐
Java中的算法优化与复杂度分析
在Java开发中,理解和优化算法的时间复杂度和空间复杂度是提升程序性能的关键。通过合理选择数据结构、避免重复计算、应用分治法等策略,可以显著提高算法效率。在实际开发中,应该根据具体需求和场景,选择合适的优化方法,从而编写出高效、可靠的代码。
31 6
|
2月前
|
监控 算法 Java
jvm-48-java 变更导致压测应用性能下降,如何分析定位原因?
【11月更文挑战第17天】当JVM相关变更导致压测应用性能下降时,可通过检查变更内容(如JVM参数、Java版本、代码变更)、收集性能监控数据(使用JVM监控工具、应用性能监控工具、系统资源监控)、分析垃圾回收情况(GC日志分析、内存泄漏检查)、分析线程和锁(线程状态分析、锁竞争分析)及分析代码执行路径(使用代码性能分析工具、代码审查)等步骤来定位和解决问题。
|
2月前
|
分布式计算 Java MaxCompute
ODPS MR节点跑graph连通分量计算代码报错java heap space如何解决
任务启动命令:jar -resources odps-graph-connect-family-2.0-SNAPSHOT.jar -classpath ./odps-graph-connect-family-2.0-SNAPSHOT.jar ConnectFamily 若是设置参数该如何设置
|
2月前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
76 2
|
2月前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
48 2
|
3月前
|
Java
让星星⭐月亮告诉你,Java synchronized(*.class) synchronized 方法 synchronized(this)分析
本文通过Java代码示例,介绍了`synchronized`关键字在类和实例方法上的使用。总结了三种情况:1) 类级别的锁,多个实例对象在同一时刻只能有一个获取锁;2) 实例方法级别的锁,多个实例对象可以同时执行;3) 同一实例对象的多个线程,同一时刻只能有一个线程执行同步方法。
27 1
|
3月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
66 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
3月前
|
Java
如何从Java字节码角度分析问题|8月更文挑战
如何从Java字节码角度分析问题|8月更文挑战