【问题标题】:Adding an edge to a tree graph so as the new maximum distance between any two vertices is minimum possible向树形图中添加一条边,以使任意两个顶点之间的新最大距离尽可能小
【发布时间】:2016-01-30 19:51:41
【问题描述】:

我一直在尝试解决以下问题(请注意,这不是家庭作业,我只是在使用去年课程的作业练习考试):http://i.imgur.com/VqgKvkh.png

我希望有人来验证或改进我完成这项任务的方法,因为我不确定是否有更快的方法(或者我所做的是否完全正确,真的)。

我的解决方案:

1) 首先,我计算每个望远镜之间的距离(使用勾股定理),给我一个 O(V^2) 复杂度过程,但考虑到 V 的最大值是 300,这还不错。我构造使用这些加权边的完整图。

2) 接下来,我使用 Kruskal 算法找到该图的最小生成树,运行复杂度为 O(E log(V))。

(这是我不确定的地方)

3) 由于这是一个树形图,我可以找到它的中心,忽略边缘权重。

4) 找到中心后(考虑到单顶点中心,还没有过多考虑如何处理双顶点中心),我将此图划分为子图(一个子图与每条边相关从中心出来)

5) 对于每个顶点,我计算它到中心的距离(考虑权重) - O(E) 复杂度

6) 对于每个子图,取离中心最大距离的两个顶点 - 复杂度约为 O(V log(V))

7) 取所有以这种方式获得的顶点对,并再次从中取最大两个。如果它们不在同一个子图中,我们就完成了,并将这两个与新边连接起来。

8) 如果它们在同一个子图中,则转到 3),并在子图上递归运行。

我的问题是 - 这是我能达到的最快解决方案吗?更重要的是,它是否正确?谢谢。

【问题讨论】:

    标签: algorithm graph-theory shortest-path


    【解决方案1】:

    很遗憾,您的算法没有产生正确的答案。

    请考虑您提供的练习表屏幕截图中的第一个示例。那里有 7 个顶点,让我们按照给定的顺序从 1 到 7 对它们进行编号。我同意望远镜网络最初是最小生成树,因为描述中说明了“所有电缆的总长度是最小的”。

    以下边是我计算出的这个 MST 的边(使用建议的顶点编号):

    {1,3}, {2,3}, {3,4}, {4,5}, {4,6}, {6,7}
    

    使用您找到中心的方式,中心是顶点 4,因为每个其他顶点距它最多 2 跳。现在让我们按照您的建议将 MST 划分为其子图。有 3 个子图(我使用它们的一组顶点来识别它们):

    1. {1,2,3}
    2. {5}
    3. {6,7}

    因此,离中心最远的顶点是

    {2,5,7}
    

    很清楚,从顶点 2 到顶点 7 的距离最高。我使用勾股定理计算出了 9.99 = sqrt(10) + 2 + sqrt(8) + 2 的距离。正如您所建议的,您的解决方案是连接顶点 2 和顶点 7 以最小化直径。

    但有一个更好的解决方案:连接顶点 3 和顶点 7(如练习中给出的解决方案)。原因是从顶点 1 到顶点 7 的距离从 9.06 = sqrt(5) + 2 + sqrt(8) + 2 下降到 8.82 = sqrt(10) + sqrt(32)。使用您的解决方案,从顶点 1 到顶点 7 的最小距离仍为 9.06,这并未达到最佳效果。


    其次,不需要您在第 8 步中建议的递归。它是一棵树,那么三个子图中的一个如何在不通过中心的路线上连接到另一个?如果是,则该图将包含一个循环,因为子图已经通过中心连接。


    第三,在密集图上,最好使用 Prim-Dijkstra 来实现 O(E + Vlog(v)) 的 MST。它很容易实现,例如,您可以在 wikipedia 上查找它。不过我想你已经知道了。


    最后,如何产生正确的结果?

    如您所见,如何使用启发式方法找到边缘并不明显,因为您的想法没有成功。

    什么是天真的解决方案? 您几乎可以选择每个顶点对,即 O(n^2) 多个候选边。要(天真地)计算它的直径,您需要 O(n^2)。因此,您可以尝试每条边并计算插入此附加边的树的直径。最后,您输出最小直径。这将是 O(n^2 * n^2) = O(n^4)。

    我们怎样才能做得更好?我喜欢先考虑简单的解决方案,因为您会知道需要查看哪些内容。从那里您开始删除不必要的操作。您正确发现的是最长的路径需要变短(否则直径不会改变)。换句话说,您添加的边必须连接位于最长路径上的两个顶点。但是你不知道是哪两个。您可以轻松地构建每个顶点都是最长路径的一部分的示例,但是对于分布良好的望远镜网络,最长路径上的顶点要少得多。现在您只尝试沿最长路径插入边并在 O(n^2) 中再次计算新直径。如果你在最长的路径上有 k 个顶点,你会得到 O(n^2 k^2)。

    总结:

    1. 使用 Prim 算法计算生成树 -> O(n^2) 在您的完整图上
    2. 计算树的最长路径,即直径 -> O(n^2) 得到最长路径上的所有 k 个顶点
    3. 尝试在这条最长路径上的所有顶点对之间一次添加一个 (O(k^2) many) 边,并存储所有直径的最小值,即您必须一次又一次地重新计算直径 ( O(n^2))。总计:O(n^2 k^2)

    如果我们能改进计算直径的时间就好了。对于在线性时间内起作用的树,请参阅Linear algorithm of finding tree diameter。您的图表最初是一棵树,但您一次最多添加一条边,即它仍然几乎是一棵树。因此,您需要做的就是找到原始树中最远的两个节点 u1、v1,然后在我们的算法中插入一条边 e={u,v} 时,您删除一条不同的边比顶点 u 处的 e ,这样循环就消失了,你又得到了一棵树。现在您再次找到最远的顶点 u2、v2。现在您计算四个顶点 u1、u2、v1、v2 之间的最大距离,这是您在线性时间内的直径。

    这会将您的运行时间缩短到 O(n*k^2 + n^2)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-17
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-19
      相关资源
      最近更新 更多