我有以下代码来查找树的直径:
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),是否可以将其优化为线性时间?您可以使用伪代码。
答案 0 :(得分:10)
这是一个线性时间复杂度的简单算法:
1)选择一个任意顶点v
2)使用BFS从v
找到最远的顶点(让我们称之为u
)。
3)再次使用BFS从u
找到最远的顶点(让我们称之为t
)。
然后distance(u, t)
是直径
BFS只被调用两次,因此时间复杂度是线性的。
答案 1 :(得分:8)
作为对其他答案的补充,可以按照以下方式进行证明:
让我们首先将树中直径的两端表示为s
和t
,函数d(u, v)
表示节点u
和节点{{}之间的距离1}}。
现在我们选择一个任意节点v
,然后我们有2个案例:
X
在直径上; X
直径 。对于案例1,通过执行(2)(@ user2040251的答案中描述的算法的第二步)很容易看出,我们将获得X
或d(X, s)
。如果我们得到其他内容,请说d(X, t)
,那么d(X, u)
和u
或s
可以形成比t
更长的路径,这与事实相矛盾。因此,通过做(3),我们将获得d(s, t)
。
对于案例2,通过做(2),我们有2个案例:
d(s, t)
开始的最长路径在直径上至少包含1个点; X
开始的最长路径不会与直径共享任何点。对于案例2.1,我们将第一个交叉点表示为X
。由于案例1,我们知道从Y
开始的最长路径必须以Y
或s
结束。因此,在这种情况下,从t
开始的最长路径必须以X
或s
结束。因此,通过执行(3),我们将获得t
。
对于案例2.2,我们用d(s, t)
作为X
表示最长路径的另一端。由于Z
或X
都不在直径上,并且Z
,X
,Z
,s
位于同一棵树上,可以得出结论必须是路径t
到V
上的节点X
,指向路径Z
上的节点W
的链接{ {1}} 即可。因为s
到t
是从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
因为X
到d(Z, V) + d(V, W) + d(W, s) < d(X, Z)
是从X
开始的最长路径;
添加2个表达式:
Z
最后,我们有Z
,这与事实相矛盾。