📌  相关文章
📜  由至少一个黑边组成的长度为 K 的节点序列的计数(1)

📅  最后修改于: 2023-12-03 15:40:56.661000             🧑  作者: Mango

计算长度为 K 的节点序列中至少包含一个黑边的数量

在计算图的路径数量时,经常需要计算长度为 K 的节点序列中至少包含一个黑边的数量。黑边指的是一条连接两个相邻节点的边,而白边则是连接不相邻节点的边。

解析

要计算长度为 K 的节点序列中至少包含一个黑边的数量,可以考虑使用排除法。具体来说,我们需要计算长度为 K 的节点序列中不包含任何黑边的数量,记作 $A$,然后用总数量减去这个结果,即 $N - A$,就可以得到至少包含一个黑边的数量。

具体实现时,可以使用动态规划的方法。假设 $dp[i][j]$ 表示长度为 $i$,以节点 $j$ 结尾的节点序列中不包含任何黑边的数量,那么有如下递推公式:

$$ dp[i][j] = \sum_{k \in nei(j)} dp[i-1][k] - dp[i-2][j] \qquad (i > 2) $$

其中 $nei(j)$ 表示节点 $j$ 的相邻节点集合,$\sum$ 表示对集合中的所有元素求和。

接下来我们分别对公式中的两个部分进行解释。

  • $\sum_{k \in nei(j)} dp[i-1][k]$

这一部分表示在长度为 $i-1$ 的节点序列中以相邻节点 $k$ 结尾的数量之和。也就是说,我们可以从以相邻节点 $k$ 结尾的所有长度为 $i-1$ 的节点序列中,添加一个以节点 $j$ 结尾的白边,得到一个以节点 $j$ 结尾、长度为 $i$ 的节点序列。

  • $- dp[i-2][j]$

这一部分表示在长度为 $i-2$ 的节点序列中以节点 $j$ 结尾的数量。可以看作特殊情况:以 $j$ 结尾的节点序列中,只包含一个节点,即不存在黑边,所以需要额外减去这种情况的数量。

最终的答案为 $N - A = \sum_{j=1}^n dp[K][j]$,即长度为 $K$,以任意节点结尾的节点序列中不包含任何黑边的数量之和。

代码实现

下面是 Python 代码的实现,时间复杂度为 $O(Kn^2)$:

def count_sequences(n: int, K: int) -> int:
    # 构造邻接矩阵
    graph = [[0] * (n+1) for _ in range(n+1)]
    black_edges = [(1, 2), (2, 3), (3, 4), (2, 5), (4, 5), (5, 6), (4, 7), (6, 7), (7, 8)]
    for i, j in black_edges:
        graph[i][j] = graph[j][i] = 1

    # 动态规划
    dp = [[0] * (n+1) for _ in range(K+1)]
    for i in range(1, n+1):
        dp[1][i] = 1
    for i in range(2, K+1):
        for j in range(1, n+1):
            s = sum(dp[i-1][k] for k in range(1, n+1) if graph[j][k])
            dp[i][j] = s - dp[i-2][j]

    # 计算答案
    return sum(dp[K][j] for j in range(1, n+1))

需要注意的是,如果输入的图不是固定的,需要根据实际情况构造邻接矩阵。此外,当 $K=1$ 时,结果直接为 $n$,不需要进行动态规划的计算。