ABC326G Unlock Achievement 题解
需要注意,以下我们将题目中提到的变量全部转为小写。
容易发现,若我们假定所有成就都会达成,那么我们需要考虑的就是一个最小化投入的问题。再观察数据范围,\(n\) 和 \(m\) 都是极小的 \(50\) 级别,合理地猜测使用最小割解决。
为啥想到用最小割?
下面会讲到把每个技能拆成五个节点,对应五个等级,容易发现这些 技能等级 和 成就 都只有达成 or 未达成两种情况,那么根据割的定义,割可以把图分成与源点相连的部分和与汇点相连的部分,自然达成未达成的情况就决策出来了。
首先,建立超级源点 \(s\) 和超级汇点 \(t\),之后,定义顶点 \(A(x, y)\) 表示 \(x\) 技能的第 \(y\) 级(\(x\in [1, n],\ y\in [1, 5]\)),定义顶点 \(B(z)\) 表示第 \(z\) 项成就(\(z\in [1, m]\))。
开始连边,每个技能初始都是 \(1\) 级,我们连接边 \(s\to A(i, 1)\),容量为 \(+\infty\)。
之后,每个技能升级需要 \(c_i\) 块钱,我们对于 \(j\in [1,4]\),连接边 \(A(i, j)\to A(i, j+1)\),容量设为 \((j - 1)\times c_i\)。
这里技能内不可能出现 下一级达成但上一级未达成 的情况(即等级之间有依赖关系),所以要连接一条反边容量为 \(+\infty\)。
之后,连接边 \(A(i, 5)\to t\),容量设为 \(4\times c_i\),表示这个技能完成了升级。
之后思考,如果我达成了某项成就,我就会获得一些钱,那么如何把他转化成 投入 呢?注意到前面提到 假定所有成就都会达成,于是我的决策就变成了 选择哪项成就不达成,最小化不达成所带来额外的代价,所以连边 \(s\to B(i)\),容量为 \(a_i\)。
这里需要注意;达成 \(\forall j\in [1, n],\ A(j, l_{i, j})\) 是达成 \(B(i)\) 的充要条件。为了避免技能升级升够了成就还没达成的情况,由当前成就向这 \(n\) 个技能等级连边,容量为 \(+\infty\)。
最后答案即为 \(\sum a_i - \operatorname{maxflow}(s, t)\)。
至此我们成功做完了这一题。注意需要开 long long,以及使用 ACL 能省不少事。