noi.ac 2021 七一挑战赛 T2

大致题意(有简化)

给定一个 \(n\) 个点,\(m\) 条边的 DAG,边有边权。

选出一棵根向生成森林。其中有 \(X\)\(Y\) 两种权值:

  • 选择一条边对 \(X\) 的贡献为边权;
  • 对于 \(u\) 的第 \(i\) 个孩子,对 \(X\) 还有 \(n - i + 1\) 的贡献;
  • \(Y\) 定义为叶子个数。

最小化 \(\dfrac{X^k}{Y}\),其中 \(k \in \{1, 2\}\)

做法

思路大致来自 \(n\) 次费用流限制 \(Y\) 值的讨论。

构造最大费用流模型。

定义 \(\infty\) 是一个远大于最短路长度的有限数

  • 将每个点拆为入点 \(u\)、出点\(u'\)
  • \(S\) 向所有 \(u\) 连容量 \(1\) ,价值 \(-n\) 的边,用于提供叶子的流量,且 \(S\) 无其他出边;(这保证了 \(\operatorname{flow}(S) = Y\)
  • 非叶子节点的流量由孩子提供;对于边 \((u, v, w)\),连接 \(u' \to v\),容量 \(1\),价值 \(w\) 的边;
  • 每个点的入点和出点之间存在一条容量为 \(1\) 的边,价值为 \(n + \infty\) (其中 \(+\infty\) 保证了由 \(S\) 的流量(叶子)构造的森林包含了每一个点;\(n\) 用于提供 \(u\) 的第一个孩子的贡献,若 \(u\) 是叶子,则用 \(S \to u\)\(-n\) 价值抵消)
  • 对于 \(u\)\(T\) (注意不是 \(u'\))依次连接容量为 \(1\),边权依次为 \(n - 1, n - 2, \dots, 1\) 的边,用于消除 \(1\) 个以上孩子的流量,以及计算贡献;
  • 对于 \(u'\)\(T\) 连价值 \(0\) 的边,若 \(u\) 为某棵树的根,那么这条边用于保证 \(u,u'\) 的边存在 \(1\) 的流量,保证正确。

通过这个模型,我们可以准确控制当前 \(Y\) 值,且如果价值大于 \(n \times \infty\),那么可以保证构造出合法的森林。

因此只需要 \(n\) 次增广来枚举 \(Y\) 值即可计算出答案。

如果使用 Dijkstra 费用流,动态加入 \(n - 1, n - 2, \dots, 1\) 的边,复杂度 \(\mathcal O(n(n + m) \log n)\)

posted @ 2021-07-01 22:56  RiverHamster  阅读(212)  评论(3编辑  收藏  举报
\