路径的“长度”是路径中的边数。
给定一个源顶点和一个目标顶点,我想找到路径数从源顶点到给定长度 k的目标顶点。
我们可以根据需要多次访问每个顶点,因此如果从a
到b
的路径如下:a -> c -> b -> c -> b
则认为它有效。这意味着可以有周期,我们可以多次通过目的地。
两个顶点可以通过多个边连接。因此,如果顶点a
顶点b
通过两条边连接,那么路径a -> b
通过边1和a -> b
通过边2被认为是不同的。
顶点数N是< = 70,而路径长度K是< = 10 ^ 9.
由于答案可能非常大,因此应以模数形式报告。
这是我到目前为止所想的:
我们可以使用breadth-first-search而不将任何顶点标记为已访问,在每次迭代时,我们会跟踪该路径所需的边数'n_e'以及产品'p'我们路径中每条边的重复边数。
如果n_e
大于k,搜索搜索应该终止,如果我们到达n_e
等于k的目的地,我们就会终止搜索并将p
添加到计数中路径数量。
我认为我们可以使用深度优先搜索而不是广度优先搜索,因为我们不需要最短路径,并且在广度优先搜索中使用的Q的大小可能不够。
我正在考虑的第二种算法与使用Floyd Warshall's Algorithm方法的this类似。只有我们不需要最短的路径,所以我不确定这是否正确。
我的第一个算法的问题是'K'可以达到1000000000,这意味着我的搜索将一直运行,直到它有10 ^ 9个边缘,而n_e边缘计数将在每个级别增加1,将是非常慢,我不确定它会终止大输入。
所以我需要一种不同的方法来解决这个问题;任何帮助将不胜感激。
答案 0 :(得分:32)
所以,这是我记得的一个漂亮的图论技巧。
建立邻接矩阵A
。如果A[i][j]
和i
之间存在边缘,则j
为1,否则为0。
然后,k
和i
之间的长度j
的路径数就是A ^ k的[i][j]
条目。
因此,为了解决这个问题,构建A
并使用矩阵乘法构造A ^ k(这里适用于取幂的常用技巧)。然后只需查看必要的条目。
编辑:嗯,你需要在矩阵乘法中进行模运算以避免溢出问题,但这是一个小得多的细节。
答案 1 :(得分:2)
实际上,A ^ k的[i] [j]条目在每个简单图中显示了完全不同的“行走”,而不是“路径”。我们可以通过“数学归纳”轻松证明它。 然而,主要问题是在给定图中找到完全不同的“路径”。 我们有一些不同的算法要解决,但上面的频段如下:
(n-2)(n-3) ...(n-k)其中“k”是表示路径长度的给定参数。
答案 2 :(得分:1)
让我在上面的答案中添加更多内容(因为这是我遇到的扩展问题)。扩展的问题是
在给定的无向树中查找长度为
k
的路径数。
对于图A
的给定邻接矩阵G
,解决方案很简单,找出A k-1 和A k 然后计算对角线(或下方)上方元素中1
的数量。
我还要添加python代码。
import numpy as np
def count_paths(v, n, a):
# v: number of vertices, n: expected path length
paths = 0
b = np.array(a, copy=True)
for i in range(n-2):
b = np.dot(b, a)
c = np.dot(b, a)
x = c - b
for i in range(v):
for j in range(i+1, v):
if x[i][j] == 1:
paths = paths + 1
return paths
print count_paths(5, 2, np.array([
np.array([0, 1, 0, 0, 0]),
np.array([1, 0, 1, 0, 1]),
np.array([0, 1, 0, 1, 0]),
np.array([0, 0, 1, 0, 0]),
np.array([0, 1, 0, 0, 0])
])