证明声明:让我们使用反证法。假设u---r是树中最长的路径;对于某个节点v,既不是v---u,也不是v---r是从v到达的最长路径。相反,最长的路径是v---k。我们有两种情况:
a)u---r和v--k有一个共同的节点o。然后v--o--u和v--o--r比u---o---k短。那么o---r比o---k短。那么u---o---r不是图中最长的路径,因为u---o---k更长。这与我们的假设相矛盾。
b) u---r 和 v--k 没有共同的节点。但由于图是连通的,因此在这些路径上分别存在节点 o1 和 o2,使得它们之间的路径 o1--o2 不包含这两条路径上的其他节点。与假设相矛盾的证明与点 a 相同,但用 o1--o2 替换了简单的 o(实际上,点 a 只是点 b 的一个特例,其中 o1=o2)。这证明了该算法的正确性。
(这是Pavel Shved编写的证明,原作者可能有更简短的证明)。
去掉叶子节点。如果剩下的节点数大于2,则重复此步骤。留下的节点(或2个节点)将是您要查找的节点。
为什么这样做有效:
该节点(或节点对)位于树中最长路径P
的中间。它们到任何节点的最大距离最多为路径长度的一半(否则它不会是最长的路径)。P
上的任何其他节点显然与P
的更远端的距离比已找到的节点更远。不在P
上的任何节点n
都将其最远节点至少为(从n
到P
上最近节点的距离,称为c
)+(从c
到P
的更远端的距离),因此比算法找到的节点(或节点对)更多。
您可以依次在每个节点上使用Dijkstra算法(http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm),以查找该节点到每个其他节点的所有距离;扫描结果列表以获取到最远节点的距离。一旦您对每个节点进行了Dijkstra处理,另一个扫描将为您提供这些最大距离的最小值。
Dijkstra通常被认为具有运行时间O(v^2)
,其中v是节点数;您将对每个节点运行它一次,这将使得时间复杂度在朴素实现中增加到O(v^3)
。您可以通过存储先前节点的Dijkstra运行的结果并在后续运行中将其用作已知值来获得收益。
正如其他评论中所说: 树是一种图形——准确地说,是一个无向连通无环图——请参见"树"(图论)。