图中的每条边都有1的权重,图可能有周期,如果一个节点有自循环,它可以是从0到无穷大的任何距离,具体取决于编号。我们采取自我循环的时间。
我已经使用bfs解决了这个问题,但距离的约束是10 ^ 9的顺序,因此bfs很慢。
我们会在表单的给定图表上询问多个查询 (距离,来源) 并且o / p是从源顶点开始精确位于给定距离的节点列表。
约束
1<=Nodes<=500
1<queries<=500
1<=distance<=10^9
我有一种感觉,会有许多重复的计算作为没有。节点很小,但我无法弄清楚如何在较小的问题中减少问题。
这样做的有效方法是什么?
编辑:我已经尝试过使用矩阵取幂,但对于给定的约束,它太慢了。问题的时间限制为1秒。
答案 0 :(得分:2)
让G = (V,E)
成为您的图表,并按如下方式定义邻接矩阵A
:
A[i][j] = 1 (V[i],V[j]) is in E
0 otherwise
在此矩阵中,每个k
:
(A^k)[i][j] > 0 if and only if there is a path from v[i] to v[j] of length exactly k.
这意味着通过创建此矩阵然后计算指数,您可以轻松得到答案。
对于快速指数计算,您可以使用exponent by squaring,这将产生O(M(n)^log(k))
,其中M(n)
是nXn矩阵的cost for matrix multiplication。
在同一图表上查找不同的查询时,这也可以节省一些计算。
附录 - 声明证明:
基数:A^1 = A
,确实在A
定义中,A[i][j]=1
当且仅当(V[i],V[j])
位于E
假设:假设所有l<k
A^k = A^(k-1)*A
。从归纳假设A^(k-1)[i][j] > 0
iff,k-1
到V[i]
的路径长度为V[j]
。
让我们检查具有索引v1,v2
和i
的两个顶点j
。
如果它们之间存在长度为k
的路径,请将其设为v1->...->u->v2
。让u
的索引为m
。
来自i.h. A^(k-1)[i][m] > 0
因为有一条路。另外A[m][j] = 1
,因为(u,v2) = (V[m],V[j])
是边缘。
A^k[i][j] = A^(k-1)*A[i][j] = A^(k-1)[i][1]A[1][j] + ... + A^(k-1)[i][m]A[m][j] + ... + A^(k-1)[i][n]A[n][j]
从A[m][j] > 0
和A^(k-1)[i][m] > 0
开始,然后是A^(k-1)*A[i][j] > 0
如果没有这样的路径,那么对于每个顶点u
,使得(u,v2)是边缘,没有从k-1
到{{v
的长度u
的路径1}}(otherweise v1->..->u->v2
是一条长度为k
}的路径。
然后,使用归纳假设我们知道A^(k-1)[i][m] > 0
然后A[m][j] = 0
,对于所有m
。
如果我们在定义A^k[i][j]
的总和中分配,我们会得到A^k[i][j] = 0
<强> QED 强>
小注意:从技术上讲,A^k[i][j]
是i
和j
之间的路径数,其长度恰好为k
。这可以证明与上面类似,但更多地关注细节。
为了避免数字增长过快(这会增加M(n)
,因为你可能需要大整数来存储该值),并且因为你不关心0/1以外的值 - 你可以将矩阵视为布尔值 - 仅使用0/1值并修剪其他任何值。
答案 1 :(得分:-1)
如果图表中有周期,那么您可以推断cycle * N + 1
中每个相邻节点之间存在链接,因为您可以根据需要进行迭代。
这让我想到了这个想法,我们可以利用这些循环来发挥我们的优势!
在检测周期时使用BFS,我们计算offset + cycle*N
,然后我们接近目标(K)
很容易搜索K.
e.g。
A - &gt; B - &gt; C - &gt; D - &gt;乙 K = 1000; S = A;
A - 0
B - 1
C - 2
D - 3
B - 1(+ 4N)
在这里你可以检查k - (1+4N) = 0
&gt;的floor() 1000 - 1 - 4N = 0
&gt; 999 = 4N
&gt; N=249
=&gt;最好的B是249*4 + 1
= 997
更简单的方法是计算:round(k - offset, cycle)
A(BCD){249}BCD