1 条题解

  • 0
    @ 2025-10-23 0:21:40

    核心思路

    1. 状态设计

    由于边权只有 1,2,31, 2, 3,我们可以将每个节点拆成 3 个状态:

    • v1v_1: 到达 vv 且最后一步走的是长度为 11 的边
    • v2v_2: 到达 vv 且最后一步走的是长度为 22 的边
    • v3v_3: 到达 vv 且最后一步走的是长度为 33 的边

    实际上代码中用的是:

    • 3v23v-2: 表示还需要走 1 步才能完成一条完整路径
    • 3v13v-1: 表示还需要走 2 步才能完成一条完整路径
    • 3v3v: 表示还需要走 3 步才能完成一条完整路径

    2. 转移矩阵构建

    状态转移规则:

    • 3u23u-23v23v-2: 需要边权 11 的边 uvu→v
    • 3u13u-13v23v-2: 需要边权 22 的边 uvu→v
    • 3u3u3v23v-2: 需要边权 33 的边 uvu→v

    内部转移(延迟计数):

    3v-2 → 3v-1 → 3v
    

    这样就把长边拆成了多个长度为 1 的"步骤"。

    3. 路径计数公式

    fL[v]f_L[v] 表示长度为 LL 的到达 vv 的路径数。

    转移:

    $$f_L[v] = \sum_{u→v \text{ with weight } w} f_{L-w}[u] $$

    由于 w{1,2,3}w \in \{1,2,3\},这是三阶线性递推,可以用矩阵快速幂。

    4. 累计路径数

    我们要求的是长度 ans\le ans 的路径总数是否 k\ge k

    在矩阵中加入一个累计节点 ss

    • 从每个完整路径状态 3v23v-2 连到 ss(计数一次)
    • ss 自环保持累计和

    这样矩阵的 [start][s][start][s] 就是长度 \le 当前幂次的路径总数。

    5. 二分答案

    使用倍增(二进制拆分)来二分:

    • 从高位到低位尝试
    • 用矩阵快速幂检查路径数
    • 如果 count<kcount < k,就加上这一位

    6. 边界处理

    • 初始状态:每个节点作为起点,w.a[3v2][3v2]=1w.a[3v-2][3v-2] = 1
    • 最终答案要减去 nn(去掉长度为 0 的路径)
    • __int128min(..., L) 防止溢出

    时间复杂度

    • 矩阵大小 O(n)O(n)
    • 矩阵乘法 O(n3)O(n^3)
    • 二分 O(logk)O(\log k)
    • 总复杂度 O(n3logk)O(n^3 \log k),对于 n40n \le 40 可接受

    这种状态拆分+矩阵快速幂+二分的方法巧妙处理了边权多样性和超大 kk 的问题。

    • 1

    信息

    ID
    3850
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者