Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 查找MST的所有关键边_Algorithm_Graph Theory_Graph Algorithm_Minimum Spanning Tree - Fatal编程技术网

Algorithm 查找MST的所有关键边

Algorithm 查找MST的所有关键边,algorithm,graph-theory,graph-algorithm,minimum-spanning-tree,Algorithm,Graph Theory,Graph Algorithm,Minimum Spanning Tree,我有一个问题来自Robert Sedgewick关于算法的书 临界边。从图中删除会导致 要增加的MST权重称为临界边。演示如何查找图形中的所有关键边 与E log E成比例的时间图。注:此问题假设边权重 不一定是不同的(否则MST中的所有边都是关键的) 请提出一个解决这个问题的算法 我能想到的一种方法就是及时完成任务。 我的方法是运行kruskal算法 但是每当我们遇到一条边,它在MST中的插入会创建一个循环,如果 循环已包含具有相同边权重的边,则已插入的边将不是关键边(否则所有其他MST边都是

我有一个问题来自Robert Sedgewick关于算法的书

临界边。从图中删除会导致 要增加的MST权重称为临界边。演示如何查找图形中的所有关键边 与E log E成比例的时间图。注:此问题假设边权重 不一定是不同的(否则MST中的所有边都是关键的)

请提出一个解决这个问题的算法

我能想到的一种方法就是及时完成任务。 我的方法是运行kruskal算法

但是每当我们遇到一条边,它在MST中的插入会创建一个循环,如果 循环已包含具有相同边权重的边,则已插入的边将不是关键边(否则所有其他MST边都是关键边)


这个算法正确吗?如何扩展此算法以在时间E日志E中执行此任务。

是的,您的算法是正确的。我们可以通过比较Kruskal算法的执行与类似的执行来证明这一点,在类似的执行中,一些MST边e的代价变为无穷大。在第一次执行之前,两次执行都是相同的。在e之后,第一次执行的连接组件比第二次少一个。这种情况持续存在,直到在第二次执行时,认为边e'连接了e将具有的组件。由于边缘e是迄今为止建造的森林之间的唯一区别,因此它必须属于e'所创建的循环。在e'之后,执行会做出相同的决定,林中的区别在于第一次执行有e,第二次执行有e'

实现该算法的一种方法是使用动态树,一种表示标记林的数据结构。此ADT的一种配置在对数时间内支持以下方法

  • MakeVertex()-构造并返回新顶点
  • 链接(u、c、v)-顶点u和v不得连接。以c为代价创建从顶点u到顶点v的未标记边
  • 标记(u,v)-顶点u和v必须是边e的端点。马克e
  • 已连接(u,v)-指示顶点u和v是否已连接
  • FindMax(u,v)-顶点u和v必须连接。返回从u到v的唯一路径上未标记边的端点以及该端点的最大开销。此边的端点按其在路径上的显示顺序给出

我不认为这在实践中是一个好的算法。动态树木,如瑞士军刀,用途广泛但复杂,通常不是完成工作的最佳工具。我鼓励您考虑如何利用这样一个事实,即我们可以等到处理完所有边后再确定临界边是什么。

我认为您建议的临界边条件是正确的。但是没有必要找到一个循环并测试它的每一条边

Kruskal算法以增加权重的顺序添加边,因此可以将边添加序列分解为等重边添加块。在每个等重块中,如果有多条边连接相同的两个组件,则所有这些边都是非关键边,因为可以选择其他任何一条边。(我说它们都是非关键的,因为我们实际上没有得到一个特定的MST作为输入的一部分——如果我们是,那么这将确定一个特定的边来称为非关键的。Kruskal实际选择的边只是初始边排序的人工制品,或者排序是如何实现的。)

但这还不够:可能是将权重为4或更小的所有边添加到MST后,我们发现有3条权重为5的边,连接组件对(1,2)、(2,3)和(1,3)。虽然这3条边中的1条以上连接的组件对不多,但我们只需要(任意)2条——使用所有3条边将创建一个循环

对于每个等权重块(权重为w),我们实际需要做的是(从概念上)创建一个新的图,其中MST的每个组件(即使用权重小于w的边)都是一个顶点,当这些组件之间存在权重为w的边时,两个顶点之间就有一条边。(这可能会导致多条边。)然后,我们在该图的每个组件上运行DFS以查找任何循环,并将属于该循环的每条边标记为非关键。DFS需要O(nEdges)时间,因此每个块(其大小总和为E)的DFS时间之和将为O(E)


请注意,Kruskal的算法需要时间O(Elog E),而不是您似乎暗示的时间O(E)——尽管像Bernard Chazelle这样的人已经接近线性时间MST构造,但TTBOMK还没有人做到这一点!:)

我不明白为什么dfs时间之和是O(E)。考虑这一图,DFS每第三步遍历KruSkAl算法3, 5, 7次、9, 11次顶点不是正确的吗?这导致稀疏图至少有O(V^2)额外的时间(我不确定如何生成E,这对密集图来说是一个糟糕的测试,不过很抱歉,我发布了NecroPost))目前我正在寻找ElogV解决方案(实际上这是在Sedgewick的书中提出的)@Ralor:我的O(E)关于DFS时间总和的说法有点错误,因为您还需要时间来维护“组件图”(到目前为止,在该图中,每个顶点都是MST的一个组件,并且每个边都是原始图中的一条加权w边),并且每个操作至少需要反向阿克曼时间。(处理原始图中的每个等重边块会导致在组件图中合并一些顶点子集,并提取新的边子集。)然后,请注意,DFS将恰好访问原始图中的每条边一次。