CF132E Bits of merry old England

传送门

构图好题。郑哥的题解

每一个输出的位置看作先分配变量(赋值或者用前面的),再输出。

给每个位置拆三个点 \(v_{i,1/2/3}\)\(v_{i,1}\) 的流入表示这个位置的 "空变量" 数量(包括有值但是我们选择让它不重复使用的变量);\(v_{i,2}\) 有流入表示分配好了这个输出位置的变量;\(v_{i,3}\) 有流入表示输出好了。

(这里拆三个点而不是两个的原因:我们需要 \(v_{i,2}\rightarrow v_{i,3}\) 的边有下界来保证一定有输出)

然后跑上下界,可以得到最小代价。

怎么求方案?(这才是难点吧)

用一个 set 维护当前的空变量。同时给每个输出位置记录一个 \(prt_i\) 表示这个位置输出的变量名字是什么。

循环 \(i\leftarrow 1\sim n\),如果 \(v_{i,1}\rightarrow v_{i,2}\) 有流量,说明在这个位置是重新赋值的,从 set 里面取一个变量用即可。

然后看 \(v_{i,3}\rightarrow v_{nxt[i],2}\),如果有流量说明这次的变量保留到了 \(nxt[i]\) 使用。令 \(prt_{nxt[i]}\leftarrow prt_i\);如果没流量,其实就等同于 \(prt_i\)\(i\) 这个位置就寿终正寝了,把它放进 set 里面作为空变量。

我们这么做的依据:如果在位置 \(i\) 使用了一个变量并保留到 \(j\) 使用,则 \(i<k<j\) 的位置 \(k\) 如果和 \(i\) 输出相同,也一定使用了 \(prt_i\)

另外这也是因为上下界网络流的结果删除 \(t\rightarrow s\) 的边就是解。

posted @ 2024-06-30 10:29  FLY_lai  阅读(6)  评论(0编辑  收藏  举报