问题描述
我必须给出如下算法:
给定一个无向连通图G,给出一种算法,该算法找到两个节点x,y,使其距离至少为图的直径的一半。证明任何索赔。
我假设我必须从任意节点运行BFS并找到其最远的节点才能找到直径。然后找到距离大于直径一半的两个探索节点。 但是我怀疑这是最佳选择,并寻求解决方案。在运行BFS来查找直径时,是否还有其他方法可以同时找到这两个必需的节点?这样复杂度仍然是多项式。 任何指导或提示,将不胜感激!
解决方法
图的直径(我们称其为D
)是其任何节点之间的最大距离(=最小跳数)。
选择任何节点并执行BFS,同时为每个节点保留从初始节点开始的跳数。这需要O(V),因为您将一次访问所有节点。请注意,此number of hops
也是shortest distance to v from the root
-我将其称为d(root,v)
。
现在,以从根开始跳数最多的叶子z
为例。恭喜,d(root,z) >= D/2
,因为
引理:对于直径为x
的连通图中的任何节点D
,必须存在一个至少为{{1}的节点y
}。
证明:如果不是这样,则将存在某个节点D/2
,因此对于所有x
,y
(带有{{1 }}。但是,然后,通过d(x,y) = D/2 - k <= D/2
,我们最多可以找到k>=1
中从任何节点到所有其他节点的路径-因此,图的直径不能为x
,而是{{1 }}。
那实际上是一个棘手的问题,但是我想我明白了。有趣的是,您的部分错误解决方案使我走上了正确的道路。
让我们在这里复制一些定义:
- 图中两个顶点之间的距离是最短路径中的边数
- 顶点
v
的偏心度是v
与任何其他顶点之间的最大距离 - 图形的直径
d
是图形中任何顶点的最大偏心率。也就是说,d
是任何一对顶点之间的最大距离
真正的问题是实际找到直径,这并非易事。要找到直径,您不能仅选择任何节点并运行BFS-在这种情况下,您只能找到与该节点具有最大距离(偏心距)的节点,但直径不是。要真正找到直径,您必须在每个节点上都运行BFS(=偏心率),并且获得的最大距离是直径(有一些更好的算法,但正如我所说,这不是一件容易的事)。
但是!您根本不必知道直径。如果您实际上是从随机节点运行BFS,并且发现距离(偏心距)最大的节点-这就是您算法的解决方案。 x
将是您的起始节点,y
将是距离最大的节点。
为什么?如果您想象这样的超级简单图
您可以看到直径在节点1和节点4之间。因此,无论从哪个点运行BFS,该点都必须位于中间(这意味着直径为直径的一半)或不位于中间。中间,然后是距离最大的节点,其距离必须甚至大于直径的一半。
如果选择6或7,则它的直径路径不完全正确(因为最大距离在1-2-3-4-5之间),但这意味着您可以获得更大的距离,这对于您的任务来说是很好的
结果:从随机节点运行BFS,当它结束时,以离起始节点最大的距离(=找到偏心率并记住最远的节点),起始节点和“结束”节点为(x,y)