给定树具有 N 顶点和正数 K 。找到它们之间距离正好 K 的不同顶点对的数量。注意,对(v,u)和(u,v)被认为是同一对(1≤ N ≤50000,1≤ K ≤500)。< / p>
我无法为此找到最佳解决方案。我可以从每个顶点做BFS,并计算从那里可以到达并且距离小于或等于 K 的顶点数。但是在最坏的情况下,复杂性将是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 是最低共同祖先,因此 Y
的 X
th parent 和 u
的 Y
th parent 应该是 LCA,所以现在如果 v
的 X
th parent 和 u
的 Y
th parent 确实是同一个节点,那么我们可以说我们对节点之间距离的预先假设是正确的,并且两个节点之间的距离是v
。
您可以使用 Binary Lifting Algorithm 计算 K
复杂度中节点的 Xth 和 Yth 祖先,预处理时间为 O(logN)
,当节点第一次访问。
角落案例:
O(NLogN)
或 u
的深度与节点的计算深度匹配,则该节点是另一个节点的祖先。假设 K = 4,我们使用上面的公式得到 v
,如果我们得到 depth[lca] = 1
和 Xth
的 Yth
和 u
祖先我们将得到相同的节点 v
,这应该验证我们的假设,但事实并非如此,因为 u 和 v 之间的距离实际上是 2,如上图所示。这是因为在这种情况下 LCA 实际上是 2,为了处理这种情况,还要分别计算 1
和 X-1
的 Y-1
th 和 u
th 祖先,并检查它们是否是不一样。
最终复杂度:O(NlogN)