给定n
个顶点上的加权有向非循环图,使得每个顶点最多只有5
,最多只有5
。节点0, 1, ..., n - 1
的方向如下
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
...
n-5 n-4 n-3 n-2 n-1
边缘只能从一行中的节点到下一行中的某个节点。
我们会收到q
次查询,询问从u
到v
的最短路径长度。此处n
最高为10^5
,q
最高为10^4
。权重都是正整数。
我们能做得比O(nq)
动态编程更好(这显然在这里不起作用)?
答案 0 :(得分:2)
这似乎太好了,不好意思,如果不是......你可以得到O(n)
( EDIT :O(n^(4/3))
)预处理和O( 1)查询。
我认为您知道如何及时计算图表中所有节点之间的所有最短距离O(n^2)
。 (这确实是可能的,你似乎知道这一点)
在k
块中划分图表,每个块包含n/(5*k)
行。 (这些块应该在完整的行上开始和结束,并且两个连续的行在它们各自的第一行和最后一行上重叠)
计算每个块中所有节点(尤其是第一行和最后一行)之间的最短路径:O((n/k)^2)
。
然后你可以考虑仅包含两个块之间边界处的节点的简化图,其边值等于它们之间刚刚计算出的最短路径。这个简化图的大小为{{1} }。 及时计算该图表中的所有最短路径{.1}。
总预处理时间:O(k)
。拿O(k^2)
,您可以进行O((n/k)^2 + k^2)
预处理。
然后查询时间为k=sqrt(n)
:取v块末尾的5个节点,v块开头的5个节点(如果块不同),你只需要比较u-> v
修改强>
当然这是假的。实际上,您有k个块可用于计算最短路径,因此该步骤的总复杂度为O(n)
。所以总数为O(1)
,而k的最佳选择是O(k*(n/k)^2)
,这给出了O(n^2/k + k^2)
和总查询k=n^(2/3)
的预处理的总复杂性