问题 边长被约束时最小生成树的快速算法?


假设您有一个非负整数边长的有向图,其范围在0到U-1之间(包括0和U-1)。计算此图的最小生成树的最快算法是什么?我们仍然可以使用现有的最小生成树算法,例如Kruskal算法O(m log n))或Prim算法(O(m + n log n))。但是,对于U很小的情况,我认为应该可以做得更好。

是否存在与更传统的MST算法竞争的算法,这些算法能够利用边长被约束在某个范围内的事实?

谢谢!


6852
2018-01-15 23:25


起源

长度是否也限制为整数,或仅限于该范围? - harold
@ harold-他们是整数。我会发布一个更正。 - templatetypedef
有几个消息来源提到有一个线性时间算法,但链接到我无法查看的东西。 - harold
如果边权重限制为整数,您可以使用基于散列表的优先级队列,而不是堆(或基于任何比较) O(log(n))风格结构)。与通常的哈希队列一样,具有相同整数开销的所有项目都放在同一个桶中,您可能会遇到最坏的情况 O(1) 操作。我认为这会删除 O(log(n)) 你提到的算法的复杂性,留下类似的东西 O(m + n)... - Darren Engwirda
@DarrenEngwirda就在这里 - 如果U通常较小,你可以在线性时间内进行bucketize,然后通过从最低权重桶添加边来添加扫描,当且仅当它连接新的顶点时。优秀(在改进和简单方面)优化。 - James


答案:


Fredman-Willard在单位成本RAM上给出了整数边长的O(m + n)算法。

这可以说是没有太大的改进:没有边长的限制(即,长度是仅支持比较的不透明数据类型),Chazelle给出了O(m alpha(m,n)+ n)算法(alpha是逆Ackermann函数)和Karger-Klein-Tarjan给出了随机O(m + n)算法。

我认为Darren的想法不会导致O(m + n + U)时间算法。 Jarnik(“Prim”)不单调使用其优先级队列,因此可以多次扫描桶; Kruskal需要一个不相交的数据结构,它不能是O(m + n)。


8
2018-01-16 18:22





使用整数边权重,您可以使用bucketing来实现最坏情况下的优先级队列 O(1) 复杂性,但另外 O(U) 空间复杂性。

在您提到的MST算法中,您应该能够使用此整数结构替换基于比较的优先级队列,从而删除 O(log(n)) 依赖于复杂性要求。我希望你的整体风格最终会变得复杂 O(n + m)

基本上,您设置了一组压缩链接列表,其中每个列表都由与该存储桶关联的(整数!)成本编制索引:

struct bucket_list
{
    _cost; // array[0..N-1] holding current cost for each item

    _head; // array[0..U-1] holding index of first item in each bucket

    _next; // array[0..N-1] where _next[i] is the next item 
           // in a list for the ith item

    _prev; // array[0..N-1] where _prev[i] is the last item 
           // in a list for the ith item
};

该结构基于以下事实:每个项目一次只能在单个桶列表中。

基于这种结构,您可以实现最坏的情况 O(1) 这些操作的复杂性:

push(item, cost); // push an item onto the head of the appropriate bucket list

_pop(item, cost); // _pop an item from (anywhere!) within a bucket list

update(item, old_cost, new_cost); // move an item between buckets by combining
                                  // push and _pop

要将此结构用作优先级队列,只需维护一个索引,该索引指向要扫描的当前最小存储桶。如果您想获得下一个最低成本项目,只需从此存储桶中弹出头项目即可。如果存储桶为空,则增加存储区索引,直到找到非空存储区索引。

当然,如果 U 额外的空间复杂度变得非常大,并且在桶上稀疏分布项目的可能性可能使这种方法没有吸引力。


3
2018-01-16 00:39



此实现的复杂性还包括U,因为您必须遍历O(U)桶。 - templatetypedef
你可以说总的复杂性是 O(n + m + U)  - 桶只在整个算法中遍历一次,而不是在每一步中遍历。 - Darren Engwirda