graph - 如何获得最小重量连接子集?

时间:2012-05-02 22:20:17

标签: algorithm data-structures graph minimum-spanning-tree

这是一个消费税:

  

考虑从加权连通图G中找到边的最小权重连接子集T的问题.T的权重是T.中所有边权重的总和。给计算最小权重连通子集T的有效算法。

以下是我的内容:

  1. 我必须假设权重由正数和负数混合。只有这两种重量的混合才有意义。

  2. 我会先对边进行排序,因此负边将首先出现。

  3. 我会考虑使用Kruskal的算法,但应该进行一些修改

  4. 因为我欢迎负边缘,所以我会尝试添加尽可能多的负边缘。

  5. 此外,可以添加一些正边缘,以防万一并非所有负边缘都连接在一起,并且它们可能需要一些正边缘作为桥梁。


  6. 好的,上面是我的想法。但是当我试图弄脏手时,我就陷入了困境。

    如何始终记录可能的最小权重集?

    例如,

    {0,1}的重量为-20

    {2,3}的重量为-10

    如果{1,3}的权重为11,那么我当然不希望{1,3}

    或如果{1,3}的权重为9,那么我想要

    使用什么样的数据结构,我总能保持最小权重和该权重的顶点?


    值得注意的是,此消费税的子集寻求edges的目标。

      

    考虑找到最小权重连接子集T的问题   来自加权连通图G

    的边

    这意味着仍然需要包含所有顶点。

    此外,它不仅仅是一个MST。考虑如果顶点有两条边,一条是-1,另一条是-2。在普通的MST算法中,只会采用-2的边缘。但在这个消费税中,需要采取-1和-2来进一步降低总体重量。

1 个答案:

答案 0 :(得分:5)

我认为你的算法大部分都是正确的,但稍作修改就很难实现。

首先,必须包含每个负边缘,以便最小化所产生的重量。接下来,计算连接组件的数量c。如果c=1,您就完成了。否则,您需要额外的c-1正边缘。

现在,当您添加负边时,请将此视为Kruskal的算法过程。每个负面边缘都可以将Kruskal森林中的几棵树联合起来。但是,即使它的末端属于Kruskal森林中的同一棵树,你也可以添加负边缘 - 这与通常的Kruskal算法不同,在这种算法中你只添加那些将两个不同的树联合起来的边缘。

在此阶段之后,您将看到c连接组件的图表(它们可能不再是树)。现在像往常一样继续使用Kruskal的算法。按递增顺序处理正边缘,跟踪您使用正边缘所做的联合数量。一旦这个数字到达c-1,你就完成了。

顺便说一下,如果你将森林表示为disjoint-set data structure,那么Kruskal算法的所有过程都可以轻松实现。它只需要几行代码就可以编写,之后跟踪所做的联合数量是微不足道的。


有些伪代码如下:

sort(edges);
c := n;
for edge in edges:
    if edge.weight < 0:
        if find(edge.firstEnd) != find(edge.secondEnd):
            --c;
        unite(edge.firstEnd, edge.secondEnd);
    else:
        if c == 1: break;
        if find(edge.firstEnd) != find(edge.secondEnd):
            unite(edge.firstEnd, edge.secondEnd);
            --c;

此处unitefind是不相交集数据结构的函数。