LOJ 2270 [SDOI 2017] 天才黑客


给出一张 \(n\) 个点,\(m\) 条边的图以及一个大小为 \(k\) 的字典树,每条边有 \(x, y\) 的权值,一条路径的权值就是上面所有边的 \(x\) 之和 + 相邻两条边在字典树上的 LCA 的深度之和。
\(1\) 到每个点的最短路。
对于 \(100\%\) 的数据,\(T \leq 10\)\(2 \leq n \leq 50000\)\(1 \leq m \leq 50000\)\(1 \leq k \leq 20000\),保证满足 \(n > 5000\)\(m > 5000\) 的数据不超过 \(2\) 组。


  虚树 图论 优化连边

  直接根据 xzz 讲的做法写的,没有看题解实现,然后一顿搞,于是搞了半天,最后发现有一个在 namespace 的变量然后在全局变量里面还开了一个,终于过了样例。。

  感觉还是挺妙的!调出来了还是比较开心的!

  先将边换成点,转换成边与边的距离,对于一个点 \(x\),我们将其所有入边和出边所代表的点连边。

  比较棘手的就是这个 LCA 的深度之和,然后可以类似于 [CTSC2018] 暴力写挂 将所有点放到 Trie 树上,然后枚举作为 LCA 的这个点,然后连边。

  又因为有关键点限制,于是我们可以将所有关键点建立一颗虚树,然后有如下解法:

  1. 对于 Trie 树上每个点,新建两个点,入点和出点。
  2. 每个点的出点向父亲的出点连边权为 \(0\) 的边,父亲的入点向该点的入点连一条边权为 \(0\) 的边,表示在 Trie 树上向下向上走的情况。
  3. 每个点的入点向出点连边权为 \(dep\) 的边,代表枚举的 LCA 的 \(dep\)
  4. 对于一个入边,直接将这个点连一条到 Trie 树上的节点的边,对于出边,直接连出去即可。

  然后我们会发现有一个问题:

一个点可以走到根,然后原路返回,于是 \(dep = 0\) 可以随便走了

  于是我们还要钦定不能原路返回,防止贡献有问题。

  于是可以将第 \(3\) 点改成:

对于 \(x\) 的每个儿子 \(y\),其入点向其他儿子的出点连边权为 \(dep\) 的边权

  然后要注意对于关键点的连边要考虑连边之后向上 / 向下走的情况。

  代码(可以查看历史记录观看调题的艰辛)