在无向未加权图中查找给定长度的路径数

时间:2013-01-11 05:14:33

标签: algorithm graph routes depth-first-search breadth-first-search

路径的“长度”是路径中的边数。

给定一个源顶点和一个目标顶点,我想找到路径数从源顶点到给定长度 k的目标顶点。

  • 我们可以根据需要多次访问每个顶点,因此如果从ab的路径如下: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,将是非常慢,我不确定它会终止大输入。

所以我需要一种不同的方法来解决这个问题;任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:32)

所以,这是我记得的一个漂亮的图论技巧。

建立邻接矩阵A。如果A[i][j]i之间存在边缘,则j为1,否则为0。

然后,ki之间的长度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])
            ])