将一组顶点连接到最佳加权图形

时间:2013-09-27 08:48:04

标签: algorithm complexity-theory graph-algorithm minimum-spanning-tree traveling-salesman

这基本上是将n个目的地连接到尽可能少的道路的问题。

输入是一组顶点(a,b,...,n)

很容易计算两个顶点之间边的权重(例如两个顶点之间的笛卡尔距离)

我想要一个在欧几里得空间中给出一组顶点的算法,返回一组边,这些边构成一个连通图,边的总重量尽可能小。

在图形语言中,这是连通图的最小生成树。

我会蛮力:

  1. 定义所有顶点之间的所有可能边 - 比如你有n 顶点,然后在完整图中有n(n-1)/ 2条边
  2. 可能的边缘可以打开或关闭(2个状态)
  3. 打开/关闭所有可能的边缘 组合:2 ^(n(n-1)/ 2)!
  4. 忽略所有那些无法连接的人 图
  5. 从剩余的组合中,找到其总和的那个 边权重是所有
  6. 中最小的

    我知道这是一个NP-Hard问题。但是,实际上对于我的应用程序,我将最多有11个顶点。我希望能够在典型的现代智能手机上解决这个问题,或者至少在小型服务器上解决这个问题。

    作为第二种变体,我希望获得相同的目标,并限制每个顶点连接到最多一个其他顶点。只要图形连接,基本上从任何点开始获得单个跟踪,并在任何其他点完成。没有必要回到你开始的地方。 在图形语言中,这是开放欧几里德旅行商问题。

    一些伪代码算法会有很大帮助。

4 个答案:

答案 0 :(得分:1)

好的第一个问题是你需要建立一个Minimum Spanning Tree。有几种算法可以实现,PrimKruskal。但是,请查看完整图表处理的第一个链接,这是您的情况。

对于第二个问题,它变得有点复杂。问题变为开放Traveling Salesman Problem(oTSP)。阅读上一个链接可能集中在欧几里德和非对称上。

问候

答案 1 :(得分:0)

也许您可以尝试greedy算法:

1. Create a list sortedList that stores each pair of nodes i and j and is sorted by the 
   weight w(i,j).
2. Create a HashSet connectedNodes that is empty at the beginning
3. while (connectedNodes.size() < n)
     element := first element of sortedList
     if (connectedNodes.isEmpty())
       connectedNodes.put(element.nodeI);
       connectedNodes.put(element.nodeJ);
       delete element from sortedList
     else 
       for(element in sortedList) //start again with the first
         if(connectedNodes.get(element.nodeI) || connectedNodes.get(element.nodeJ))
           if(!(connectedNodes.get(element.nodeI) && connectedNodes.get(element.nodeJ)))
              //so it does not include already both nodes
              connectedNodes.put(element.nodeI);
              connectedNodes.put(element.nodeJ);
              delete element from sortedList
              break;
           else 
              continue;

所以我稍微解释一下第3步:

添加长节点,直到所有节点彼此连接。确保图表已连接,因为您只需添加一个节点,如果他与已在connectedNodes列表中的另一个节点有连接。

所以这个算法是贪婪的,它不能确保解决方案是最优的。但它是一个非常好的近似值,因为它总是占用最短的边缘(因为sortedList按边缘的权重排序)。

哟不会在duplicates中获得connectedNodes,因为它是HashSet,这也使运行时更快。

总而言之,运行时应该是O(n ^ 2),用于在开头和低于O(n ^ 3)的排序,因为在最坏的情况下,你在每个步骤中运行整个列表的大小n ^ 2你做n次,因为你在每一步中添加一个元素。

但更可能的是,你发现一个元素比O(n ^ 2)快得多,我认为在大多数情况下它是O(n)。

答案 2 :(得分:0)

你可以用optimap tsp求解器fron gebweb或线性程序求解器来解决travelsalesman问题和汉密尔顿路径问题。但第一个问题似乎要求最小生成树可能问题标签是错误的吗?

答案 3 :(得分:0)

对于第一个问题,有一个O(n^2 * 2^n)时间算法。基本上,您可以使用dynamic programming来缩小搜索空间。假设所有顶点的集合都是V,因此状态空间由V的所有子集组成,目标函数f(S)是连接顶点的边的权重的最小总和。 S。对于每个州S,您可以枚举所有边(u, v) u Sv位于V - S,并更新{ {1}}。检查完所有可能的状态后,最佳答案为f(S + {v})

以下是用于说明该想法的示例代码,但它是以后向方式实现的。

f(V)

对于第二个问题,对不起,我不太明白。也许你应该提供一些例子?