【问题标题】:Finding the number of paths of given length in a undirected unweighted graph在无向无权图中查找给定长度的路径数
【发布时间】:2012-12-25 16:16:55
【问题描述】:

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

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

  • 我们可以随意访问每个顶点,所以如果从ab 的路径是这样的:a -> c -> b -> c -> b,它被认为是有效的。这意味着可以有循环,我们可以多次经过目的地。

  • 两个顶点可以通过多条边连接。因此,如果顶点 a 和顶点 b 由两条边连接,则路径 a -> b via edge 1 和 a -> b via edge 2 被认为是不同的。

  • 顶点数N

  • 由于答案可能非常大,因此需要以某个数字为模进行报告。

这是我目前的想法:

我们可以使用 breadth-first-search 而不将任何顶点标记为已访问,在每次迭代中,我们都会跟踪该路径所需的边数 'n_e' 和 product 的'p'我们路径中每条边的重复边数。

如果n_e大于k,搜索应该终止,如果我们到达目的地n_e等于k,我们终止搜索并将p添加到out count of paths中。

我认为我们可以使用深度优先搜索而不是广度优先搜索,因为我们不需要最短路径,并且在广度优先搜索中使用的 Q 的大小可能还不够。

我正在考虑的第二种算法类似于Floyd Warshall's Algorithm 使用this 方法。只有我们不需要最短路径,所以我不确定这是否正确。

我的第一个算法遇到的问题是“K”可以达到 1000000000,这意味着我的搜索将一直运行到它有 10^9 条边并且 n_e 边数将在每个级别仅增加 1,这会很慢,我不确定它是否会因大量输入而终止。

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

【问题讨论】:

  • 所有边的权重都为 1 吗?
  • @DennisMeng 是的,它是一个未加权的图,我会在问题中添加它

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


【解决方案1】:

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

制作一个邻接矩阵A。如果ij 之间存在边,则A[i][j] 为1,否则为0。

那么,ij 之间长度为k 的路径数就是A^k 的[i][j] 条目。

所以,为了解决这个问题,构建A 并使用矩阵乘法构造 A^k(这里适用于求幂的常用技巧)。然后只需查找必要的条目。

编辑:嗯,你需要在矩阵乘法中进行模运算以避免溢出问题,但这是一个小得多的细节。

【讨论】:

  • "那么,i 和 j 之间长度为 k 的路径数就是 A^k 的 [i][j] 项。"由于每个条目将是 1 或 0,路径数将是 0 或 k?
  • 没有。如果你愿意,你可以做一个快速的归纳证明来证明正确性,但是 A^k 不会只有 0s 和 ks。
  • "如果 i 和 j 之间有边,则 A[i][j] 为 1,否则为 0。你自己说的
  • 是的,但这并不意味着 A^k 只有 0s 和 ks。我正在做幂运算,而不是乘以标量。
  • 好吧,通过自乘分配更多的矩阵,比如 A0=A、A1=A0*A0、A2=A1*A1 等,你最终只需要乘以最多 2* ceil(log2(K)) 次。
【解决方案2】:

实际上,A^k 的 [i][j] 条目在每个简单图中显示了总不同的“walk”,而不是“path”。我们可以很容易地通过“数学归纳法”来证明它。 但是,主要问题是在给定图中找到完全不同的“路径”。 我们有很多不同的算法要解决,但上限如下:

(n-2)(n-3)...(n-k) 其中“k”是指定路径长度的参数。

【讨论】:

  • 这确实是图论中的正确词,应该注意。寻找路径更难。
【解决方案3】:

让我在上面的答案中添加更多内容(因为这是我面临的扩展问题)。扩展问题是

在给定的无向树中找到长度为k 的路径数。

对于图G的给定邻接矩阵A,解决方法很简单,找出Ak-1和Ak,然后计算1s 在对角线上方(或下方)的元素中。

让我也添加 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])
            ])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多