具有特定距离的图中的顶点对

时间:2018-06-16 18:56:04

标签: algorithm dynamic-programming graph-theory breadth-first-search

给定树具有 N 顶点和正数 K 。找到它们之间距离正好 K 的不同顶点对的数量。注意,对(v,u)和(u,v)被认为是同一对(1≤ N ≤50000,1≤ K ≤500)。< / p>

我无法为此找到最佳解决方案。我可以从每个顶点做BFS,并计算从那里可以到达并且距离小于或等于 K 的顶点数。但是在最坏的情况下,复杂性将是2的顺序。是否有更快的方法?

2 个答案:

答案 0 :(得分:0)

您可以通过更简单的方式实现这一目标。 在树上运行DFS,并为每个顶点计算与根的距离 - 保存在数组中的那些(通过o(1)访问)。

对于图表中的每对顶点: 找到他们的LCA(最低共同祖先有算法在0(1)中做到这一点)。 假设u和v是2个任意顶点,w是它们的LCA - &gt;从u到根减去从w到根的距离 - 现在你有u和w之间的距离。为v - &gt;做同样的事情与o(1)你得到(v,w)和(u,w)的距离 - &gt;将它们加在一起得到(v,u)距离 - 现在你所要做的就是与K比较。

最终复杂度为o(n ^ 2)

答案 1 :(得分:0)

改进其他答案的方法,我们可以进行一些关键观察。

要计算两个节点之间的距离,您需要它们的 LCA(最低公共祖先)和深度,就像另一个答案试图做的那样。这里使用的公式是:

<块引用>

Dist(u, v) = depth[u] + depth[v] - 2 * depth[ lca(u, v) ]

Depth[x] 表示 x 到根的距离,从根节点开始使用 DFS 预先计算。

现在关键的观察来了,你已经有了距离值 K,假设 dist(u, v) = K 使用这个假设计算(预测?)LCA 的深度。通过将 K 代入上述公式,我们得到:

<块引用>

depth[ lca(u, v) ] = (depth[u] + depth[v] - K) / 2

既然你有了 LCA 的深度,你知道 u 和 lca 之间的距离是 depth[u] - depth[ lca(u, v) ]v 和 lca 之间的距离是 depth[v] - depth[ lca(u, v) ],让这个是 {{1 }} 和 X 分别。

现在我们知道 LCA 是最低共同祖先,因此 YXth parent 和 uYth parent 应该是 LCA,所以现在如果 vXth parent 和 uYth parent 确实是同一个节点,那么我们可以说我们对节点之间距离的预先假设是正确的,并且两个节点之间的距离是v

您可以使用 Binary Lifting Algorithm 计算 K 复杂度中节点的 Xth 和 Yth 祖先,预处理时间为 O(logN),当节点第一次访问。

角落案例:

  1. 计算出的 LCA 深度不应是分数或负数。
  2. 如果任何节点 O(NLogN)u 的深度与节点的计算深度匹配,则该节点是另一个节点的祖先。
  3. 考虑这棵树:

enter image description here

假设 K = 4,我们使用上面的公式得到 v,如果我们得到 depth[lca] = 1XthYthu 祖先我们将得到相同的节点 v,这应该验证我们的假设,但事实并非如此,因为 u 和 v 之间的距离实际上是 2,如上图所示。这是因为在这种情况下 LCA 实际上是 2,为了处理这种情况,还要分别计算 1X-1Y-1th 和 uth 祖先,并检查它们是否是不一样。

最终复杂度:O(NlogN)