首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >求树中简单路径的最小权

求树中简单路径的最小权
EN

Stack Overflow用户
提问于 2015-02-11 09:09:07
回答 3查看 1.9K关注 0票数 0

我遇到了一个问题,我们想设计一个有效的算法来寻找一条重量最轻的简单路径。(具有最小权重的简单路径)。

我认为这不是多项式解,但有些朋友说可能是O(n)或O(n^2)或O(n lg n)。好了!

程序员还是专家,能帮我吗?有什么伪码吗?

编辑:

这个问题的输入是一个边上有整数权的树T。权重可以是负的、零的,也可以是正的。路径的长度是路径中边的权重之和。如果没有重复顶点,路径就很简单。

输出:在给定的树中找到最小权重的简单路径。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-02-11 10:06:26

下面是线性解的伪代码:

代码语言:javascript
运行
AI代码解释
复制
res = 0 // A path from a node to itself has a weight 0

// Runs depth first search from the v vertex and returns the weight of
// the shortest path that starts in a descendant of v and ends in v
def dfs(v):
    // The shortest path from a descendant of v to v
    minLength = 0
    // The list of all lengths of paths coming from children
    childLengths = []
    for edge in edges(v):
        childLength = dfs(edge.to)
        // Update the result with a vertical path from the child
        res = min(res, childLength + edge.weight) 
        // Update the minLength based on the child's value
        minLength = min(minLength, childLength + edge.weight)
        childLengths.add(childLength + edge.weight)
    if childLengths.size() >= 2:
        // Update the result based on two smallest children values.
        // Finds the the first and the second minimum in a list in a linear time.
        min1 = firstMin(childLengths)
        min2 = secondMin(childLengths)
        res = min(res, min1 + min2)
    return minLength    

dfs(root)
return res

如果树没有根,我们可以选择任何一个顶点作为根。

票数 0
EN

Stack Overflow用户

发布于 2015-02-11 09:42:41

在一棵树中,每个节点之间只有一条简单的路径(这里有个证据)。

因此,即使您尝试每一对节点找到之间的路径,您也会得到一个O(n^3)算法。

一种更好的方法是为每一个节点在一次访问中找到每个其他节点的成本。这使得算法降低到O(n^2)。

票数 0
EN

Stack Overflow用户

发布于 2015-02-11 09:53:16

有一个简单的O(n)算法,它是基于这样一个事实:在一棵树中总是有一些叶子,如果我们删除一片叶子,剩下的图仍然是树。这样我们就可以一个一个地删除树叶,然后用这种方法处理所有的树(所有的边缘)。

您需要保持为每个节点找到最轻的路径。

让我们假设你正在处理一些叶子,节点n是连接到的节点叶,我们想要确保你在注视着任何一条穿过连接这个n和叶子的边缘的路径。让我们来看看照片

此处的方向仅指从较早删除的节点到其“父节点”的方向,该节点稍后将被删除,它可能取决于处理树叶的顺序n。

如果我们有一条穿过叶子的最短路径,它可以把叶子的任何“子”和其他的“子”连接起来,或者它可以把叶子的任何“子”连接到树的其余部分。

在这两种情况下,保持从任何已处理节点到当前节点的最短路径就足够了。当我们处理叶子时,我们选择最轻的为叶建立的路径,并增加与它的连接的权重,并将其与已经为n保存的最短路径进行比较,这样我们将不可避免地将n的两条最短路径进行比较,并能够将它们结合在一起,并且在处理n的所有“子”时,都会保存n的最短路径。

这是伪码。

代码语言:javascript
运行
AI代码解释
复制
for each (node in graph)
{
   node.shortest_path = 0; //zero length path from this node to this node
}
leaves = new list(all leaves in graph); //O(n) to find
int minWeight = 0; //any zero length path is minimum weight path currently found

//note that we a going to add new elements in list during the iteration
//and we will need to iterate through all of them including new added
//so in usual programming languages you will need to use for cycle
for each (leaf in leaves)
{
       //we will have last node in tree with no connection
       //because we will delete it on previous iteration
       //and we don't need to process this node
       //for this problem it is last node, 
       //but it may be not last if we have several trees instead of one
       if (no point connected to leaf) continue; 

     n = only one node still connected to leaf       
     connection = connection between n and leaf

     //check if we can make a short path which goes through n 
     //from one already processed "child" node to another
     if (leaf.shortest_path + 
         connection.weight 
         + n.shortest_path < minWeight  )
     {
         minWeight = leaf.shortest_path+connection.weight+n.shortest_path; 
     }
     //and we need to keep lightest path from any processed "child" to n
     if (leaf.shortest_path + connection.weight < n.shortest_path )
     {
          n.shortest_path = leaf.shortest_path + connection.weight;
          if(n.shortest_path < minWeight )
          {
               minWeight = n.shortest_path;
          }
     }

     //delete connection and 
     connection.delete();
     //if n is now leaf add it to leaf list
     if (n is leaf) 
     {
         leaves.Add(n);
     }
}

因此,在主循环中,我们精确地处理了每个节点一次,因此我们具有O(n)复杂度。如果需要非零长路径,但该算法没有找到,这意味着所有的边都有正权,最轻的非零长路径是最轻的边。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28460252

复制
相关文章
Java中类注释规范
如上图所示,点击右侧的+,新建Live Template,然后编辑如上图,将应用范围设为Java,如果只设comment,无法智能提示,且必须/*再按tab才行。如果有一些 $var$,可以 编辑变量 在IntelliJ IDEA中,打出的部分就会智能提醒,Enter后恩Tab即可。
用户8983410
2021/10/07
1.8K0
Kotlin中的常用类及其使用
代码的初始化工作由它负责,在调用主构造函数之前执行,这部分理论上可以进行任何工作,但建议类的初始化赋值可以放在这,其余的最好由其他专门的地方处理,采用init关键字
wresource
2023/01/31
1.1K0
【Kotlin】常用的 Kotlin 类 ② ( 枚举类 | 枚举类定义函数 | 密封类 )
Kotlin 中使用 枚举类 定义常量 , 枚举类定义格式如下 : 枚举常量 都是 枚举类 的 实例对象 ;
韩曙亮
2023/03/30
1.1K0
Java 中枚举类的使用
在日常写项目时,很多数据字典常量都需要定义和使用,同时在 Java 面试中,枚举也是一个绕不开的话题,这篇文章就来详细介绍一下枚举的定义以及使用。 01  【什么是枚举类?】 枚举类型在 C# 或 C++ 、 java 、 VB 等一些编程语言中是一种基本数据类型而不是构造数据类型。 而在C语言中则是一种构造数据类型。它用于声明一组命名的常数,当一个变量有几种可能的取值时,可以将它定义为枚举类型。 枚举类的定义就是指将变量的值一一列出来,变量的值只限于列举出来的值的范围内,使用枚举可以很方便地定义数据常量
老九君
2022/09/02
1.7K0
Java 中枚举类的使用
Java中Scanner类的使用
设A级为85分以上(包括85);B级为70分以上(包括70分);C级为60分以上(包括60分);D级为60分以下。
算法与编程之美
2023/01/03
8550
Java中Scanner类的使用
Java中的Reference类使用
Java 2 平台引入了 java.lang.ref 包,这个包下面包含了几个Reference相关的类,Reference相关类将Java中的引用也映射成一个对象,这些类还提供了与垃圾收集器(garbage collector)之间有限的交互。
huofo
2022/03/17
7220
Kotlin中级(9)- - - Kotlin类之数据类、密封类、内部类.md
上面的代码我们可以看到结构出来的变脸可以直接拿来用,比如数据体Leaf中的size属性,componentN函数群会按照数据体Leaf中属性声明的顺序,从component1到component4和size、color、shape、及vein一一对应。
Hankkin
2018/09/30
1.2K0
Java的类/方法/字段注释详解
一个程序的可读性,关键取决于注释。如果一个程序想二次开发,要读懂前面的程序代码,就必须在程序中有大量的注释文档,所以对于一个优秀的程序员来说,学会在程序中适当地添加注释是非常重要的。
JavaEdge
2020/05/26
3.2K0
匿名类中在Json中使用
匿名类 1. 第一步:定义一个类,类中有三个属性Id。Name.Height 属性类型根据“=”右边的值来推断 2. 第二步:创建这个类的对象,然后,用变量p1去指向它 3. var 表示根据右边的类型去推断var的类型
静心物语313
2020/03/24
3.1K0
匿名类中在Json中使用
【Kotlin】Kotlin Sealed 密封类 ( 密封类声明 | 密封类子类定义 | 密封类特点 | 代码示例 )
1 . 密封类作用 : 定义一个密封类 , 该类只能有有限个指定的子类 , 不能在其它文件定义其它类型子类 ;
韩曙亮
2023/03/27
1.5K0
Java中时间类中的Data类与Time类
上面我们了解了Date类,我们知道,他是一个比较老的类,且不是线程安全的,所以,我们目前基本上是使用他的升级版LocalDate。
JanYork_简昀
2022/04/11
1.8K0
Java中时间类中的Data类与Time类
About Kotlin-Kotlin中的类1About Kotlin(1)
因为是从Java的角度来学习Kotlin,在Java中,类作为第一等公民。故学习Kotlin,也先从其的类开始。
deep_sadness
2018/08/30
1.3K0
About Kotlin-Kotlin中的类2About Kotlin(2)
使用sealed修饰符修饰。其实是一组类的集合。可以用来表示受限的类的继承结构。 其也可以有子类,所有子类也必须在相同的文件中声明。 密封类从某种意义上说,它们是枚举类的扩展:枚举类型的值集也受到限制,但每个枚举常量仅作为单个实例存在,而密封类的子类可以包含多个实例并包含状态。这样又具备了枚举不具备的灵活性。
deep_sadness
2018/08/30
2.6K0
转向Kotlin——数据类和封闭类
数据类是Kotlin的一个语法糖。Kotlin编译器会自动为数据类生成一些成员函数,以提高开发效率。
蜻蜓队长
2018/08/03
9630
java中indexOf()类的基本使用
String s1 = new String("Good Good Study ,Day Day up !");
用户7886150
2021/04/06
1.3K0
关于Java中Stack类的使用
为什么不用Stack类?\n\n《Java编程思想》第四版一书中明确不建议我们使用java.util.Stack类,一直保留只是为了兼容以前的版本,在17.13.3中提到了原因。主要是因为:\n\nStack类是继承自Vector类,而不是使用Vector来实现Stack,这就产生了一个问题,Vector上可以使用的方法Stack类都可以使用,所以很容易破坏栈应有的规则。在本书的11.8中提到建议使用LinkedList实现栈。\n\nPS:Stack是为了专门实现栈而创建的类,作者在文中也提到“竟然不是用Vector来构建Stack,而是继承Vector”,可见作者也认为额外的操作是使用Stack类所不能容忍的。但这和建议使用LInkedList不能同一看待,因为一个是专用类,而另外一个是建议实现Stack的一种手段(不能因为可以实现Stack而不能有其他的操作,LinkedList毕竟不是为了Stack而生)。\n\n- 为什么不用Vector类?\nVector由于是线程安全的,所以在单线程的时候效率会叫ArrayList更低。在Java 1.2 出现ArrayList之后基本上就使用起来代替Vector。在多线程中ArrayList可以使用Collectiuons.synchronized方法来保证多线程环境下的安全使用。在本书17.13.1中提到另一个原因就是又长又难记的方法名。
用户1148830
2018/01/03
1.5K0
java 中对 BigDecimal 类使用详解
因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度。
一写代码就开心
2022/06/26
1.2K0
java 中对 BigDecimal 类使用详解
Java中Date类与Calendar类
Java中有两个与时间相关的常用类:Date类与Calendar类,开始在做题目的时候一无所知,通过查阅网上的资料有了一些基本的了解.(其实也可以查看Java的API,这是十分有效的学习方法,以后要加强这种意识).
用户8224910
2021/01/26
6440
在Android开发中怎样使用Application类
自己独立开发项目才发现以前对Application类并不是十分了解,现在开始直接搭建一个新项目的框架才重新踩过这个坑。
1025645
2018/08/23
2.2K0
在Android开发中怎样使用Application类
点击加载更多

相似问题

从java类中检索kotlin注释

115

如何使用类注释Kotlin

10

Jackson @JsonProperty注释在kotlin数据类中的使用

75

Java注释处理器-注释Kotlin类单元测试

12

生成Kotlin方法/类注释

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文