W
e
l
c
o
m
e
: )

[CSP-S 2022] 数据传输

link

题外话:考场写了个 \(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\),有:

\[\begin{cases} g_0=\min(f_0+a_{nxt, 0}, f_1+a_{nxt, 0})\\ g_1=f_0 \\ g_2=\operatorname{INF} \end{cases}\]

对于 \(K=3\),有:

\[\begin{cases} g_0=\min(f_0+a_{nxt, 0}, f_{1}+a_{nxt, 0}, f_2+a_{nxt, 0})\\ g_{1}=\min(f_0, f_{1}+a_{nxt, 1})\\ g_2=f_1 \end{cases}\]

这些递推是比较 trivial 的,大家都能想到,需要考虑一些琐碎的点:

  1. 对于 \(K=2, g_1\) 的转移:根据结论,当前走到点的前一个点必然还是原路径上的点,那么我只能从 \(x\) 走过来。

  2. 为什么要考虑 \(k=2\) 的情况,虽然 \(K=3\) 的情况中非原路径点到路径的最短距离只有 \(1\),但我可能从距离 \(x\)\(2\) 的点走到 \(nxt\),故要多考虑 \(k=2\)

  3. \(g_2=f_1\) 这一步,如果 \(f_1\) 本身到的点就是 \(nxt\),不会重吗?若最优路径选择了 \(nxt\),那么会在 \(g_0\) 被统计到,若没有,\(g_2\) 没有用处,因为我们只会走到邻接点。

发现转移柿子规模很小,考虑矩阵优化。

重新定义矩阵乘法 \(c[i][j]=\min (a_{i, k}+b_{k, j})\),发现其类似于 Floyed,因此结合律是有的。

不难写出转移矩阵:

\[\left[ \begin{aligned} f_0 && f_1 && f_2 \end{aligned} \right] \times \left[ \begin{aligned} a_{nxt, 0} && 0 && \operatorname{INF} \\ a_{nxt, 0} && \operatorname{INF} && \operatorname{INF}\\ \operatorname{INF} && \operatorname{INF} && \operatorname{INF}\\ \end{aligned} \right] = \left[ \begin{aligned} g_0 && g_1 && g_2 \end{aligned} \right], (K=2) \]

\[\left[ \begin{aligned} f_0 && f_1 && f_2 \end{aligned} \right] \times \left[ \begin{aligned} a_{nxt, 0} && 0 && \operatorname{INF} \\ a_{nxt, 0} && a_{nxt, 1} && 0\\ a_{nxt, 0} && \operatorname{INF} && \operatorname{INF}\\ \end{aligned} \right] = \left[ \begin{aligned} g_0 && g_1 && g_2 \end{aligned} \right], (K=3) \]

特别的,\(s_i\) 的转移矩阵为:

\[\left[ \begin{aligned} a_{x, 0} && \operatorname{INF} && \operatorname{INF} \\ \operatorname{INF} && \operatorname{INF} && \operatorname{INF}\\ \operatorname{INF} && \operatorname{INF} && \operatorname{INF}\\ \end{aligned} \right] \]

那么直接根据跳的方向(\(s_i \to lca\) 向上,\(lca \to t_i\) 向下) 倍增一下即可,复杂度 \(O(3^3 n \log n)\),注意空间不要开太大。

code

posted @ 2022-10-30 17:44  127_127_127  阅读(999)  评论(7编辑  收藏  举报