大致题意(有简化)
给定一个 \(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\) 值,且如果价值大于 \(Y \times \infty\),那么可以保证构造出合法的森林。
因此只需要 \(n\) 次增广来枚举 \(Y\) 值即可计算出答案。
如果使用 Dijkstra 费用流,动态加入 \(n - 1, n - 2, \dots, 1\) 的边,复杂度 \(\mathcal O(n(n + m) \log n)\)。