求树直径的线性算法

时间:2014-09-03 16:18:43

标签: algorithm tree

我有以下代码来查找树的直径:

ALGORITHM: TREE_DIAMETER (T)

maxlength ← 0
for s ← 0 to s < |V[T]|
      do temp ← BSF(T, S)
            if maxlength < temp
                   maxlength ← temp
                   increment s by 1
return maxlength

但是这个算法不能在线性时间内运行。尽可能保留上述代码的细节(例如:使用BSF),是否可以将其优化为线性时间?您可以使用伪代码。

2 个答案:

答案 0 :(得分:10)

这是一个线性时间复杂度的简单算法:
1)选择一个任意顶点v 2)使用BFS从v找到最远的顶点(让我们称之为u)。
3)再次使用BFS从u找到最远的顶点(让我们称之为t)。
然后distance(u, t)是直径 BFS只被调用两次,因此时间复杂度是线性的。

答案 1 :(得分:8)

作为对其他答案的补充,可以按照以下方式进行证明:

让我们首先将树中直径的两端表示为st,函数d(u, v)表示节点u和节点{{}之间的距离1}}。

现在我们选择一个任意节点v,然后我们有2个案例:

  1. X在直径上;
  2. X直径
  3. 对于案例1,通过执行(2)(@ user2040251的答案中描述的算法的第二步)很容易看出,我们将获得Xd(X, s)。如果我们得到其他内容,请说d(X, t),那么d(X, u)us可以形成比t更长的路径,这与事实相矛盾。因此,通过做(3),我们将获得d(s, t)

    对于案例2,通过做(2),我们有2个案例:

    1. d(s, t)开始的最长路径在直径上至少包含1个点;
    2. X开始的最长路径不会与直径共享任何点。
    3. 对于案例2.1,我们将第一个交叉点表示为X。由于案例1,我们知道从Y 开始的最长路径必须以Ys 结束。因此,在这种情况下,从t开始的最长路径必须以Xs结束。因此,通过执行(3),我们将获得t

      对于案例2.2,我们用d(s, t)作为X表示最长路径的另一端。由于ZX都不在直径上,并且ZXZs位于同一棵树上,可以得出结论必须是路径tV上的节点X,指向路径Z上的节点W的链接{ {1}} 即可。因为st是从X开始的最长路径,所以Z。同样,我们有X。添加它们并简化它们会给我们:d(X, V) + d(V, W) + d(W, t) < d(X, Z),这与d(Z, V) + d(V, W) + d(W, s) < d(X, Z)d(X, Z) > 2d(V, W) + d(s, t) > d(s, t)的直径相矛盾。

      说明案例2.2的图表:

      s

      所以我们有:

      t因为s Z | | | | | | W-------------V | | | | | | t X d(X, V) + d(V, W) + d(W, t) < d(X, Z)是从X开始的最长路径;

      Z因为Xd(Z, V) + d(V, W) + d(W, s) < d(X, Z)是从X开始的最长路径;

      添加2个表达式:

      Z

      最后,我们有Z,这与事实相矛盾。