[CSP-S 2022] 数据传输
题外话:考场写了个 \(3^3\) 巨大多恶心的分讨倍增写吐了,不仅没调出来还导致没时间仔细考虑 T1 T3 的 bug,感谢这题送我退役。
对于 \(K=1\),相当于树上路径点权和。
对于 \(K=2\),不难想到我们最终走过的 \(c\) 都在 \(s_i \to t_i\) 的树上简单路径上。因为若想走两步规避掉我的父亲,那么我拐到父亲的一个儿子,向上走还是只能到我父亲的父亲,还不如一开始就走到我父亲的父亲(\(\operatorname{LCA}\) 处类似)。
对于 \(K=3\),类似于 \(2\) 的讨论,我们最终的 \(c\) 序列只有可能是原来 \(s_i\to t_i\) 的简单路径中的点或者这些点的邻接点。
那么先预处理 \(a_{x, 0}=v_x, a_{x, 1}=\min_{(x, y)\in T} v_y\)。
设 \(dp_{x, k}\) 为当前处理完 \(s_i \to x\) 部分,现在在距离 \(x\) 为 \(k\) 的某个点上,最小的代价,\(k \in [0, 2]\),现在转移到 \(dp_{nxt}\),我们设 \(f\) 为 \(x\) 处的 \(dp\) 值,\(g\) 为 \(nxt\) 处的 \(dp\) 值。
对于 \(K=2\),有:
对于 \(K=3\),有:
这些递推是比较 trivial 的,大家都能想到,需要考虑一些琐碎的点:
-
对于 \(K=2, g_1\) 的转移:根据结论,当前走到点的前一个点必然还是原路径上的点,那么我只能从 \(x\) 走过来。
-
为什么要考虑 \(k=2\) 的情况,虽然 \(K=3\) 的情况中非原路径点到路径的最短距离只有 \(1\),但我可能从距离 \(x\) 为 \(2\) 的点走到 \(nxt\),故要多考虑 \(k=2\)。
-
\(g_2=f_1\) 这一步,如果 \(f_1\) 本身到的点就是 \(nxt\),不会重吗?若最优路径选择了 \(nxt\),那么会在 \(g_0\) 被统计到,若没有,\(g_2\) 没有用处,因为我们只会走到邻接点。
发现转移柿子规模很小,考虑矩阵优化。
重新定义矩阵乘法 \(c[i][j]=\min (a_{i, k}+b_{k, j})\),发现其类似于 Floyed,因此结合律是有的。
不难写出转移矩阵:
特别的,\(s_i\) 的转移矩阵为:
那么直接根据跳的方向(\(s_i \to lca\) 向上,\(lca \to t_i\) 向下) 倍增一下即可,复杂度 \(O(3^3 n \log n)\),注意空间不要开太大。