CodeVS 1237。
粗浅地学习了带上下界的网络流的人的代码的时间开销:1472ms。
领悟二分图精髓的人的代码的时间开销:18ms。
两种建图的顶点数相同,我的边数是后者的2/3。但是增广的次数可能很多。
优雅的模型
约束是每天的餐巾够用,目标是使费用最小。每天的餐巾有三种来源:新买的,m天前送到快洗部的,n天前送到慢洗部的。每天的餐巾有三种去路:延期处理,送到快洗部,送到慢洗部。网络流模型擅长处理的是小于等于号,然而这里是“够用”即大于等于。(1) 如果总是存在一种刚好够用的方案,它显然优于其他有冗余的方案。今天多用一些餐巾的好处是能多洗一些餐巾以备后用……这是不必要的。今天多用的餐巾如果是买的,要用的那天再买,能省去清洗费用;如果是洗的,从它被使用的那天起延期处理,今天清洗即可,今天用不着使用它。(2) 刚好够用的方案总是存在。所以,根据(1)(2),在费用最小的目标下,“够用”可以改成“恰好够用”。
- 上面的分析中,我们区分了“今天使用的”和“今天清洗的”。把“今天清洗的”作为X集合,“今天使用的”作为Y集合,我们能够建立二分图模型。今天使用的=今天清洗的=今天的需求,S->Xi,Yi->T,容量为ri,费用为0,求最大流把它们流满即满足约束。它们必能满流,因为其他边的容量都是正无穷的,见下文。
- 新买的:S->Yi,容量inf,费用p。
- 快洗:Xi->Y(i+m),i+m<=N,容量inf,费用f。
- 慢洗:Xi->Y(i+n),i+n<=N,容量inf,费用s。
- 延期处理:Xi->X(i+1),i< N,容量inf,费用0。
就是这样。
这个模型使我欣赏的地方:
1. 通过分析,把>=转为=,由于流的容量限制(<=),流量最大时满足了约束(取得等号)。“最小费用”、“最大流”两个约束很好地统一了。
2. “从源点流出的=流入汇点的”——广义的流量平衡。平时我们讲流量平衡,都是以一个顶点为对象,流入=流出。别忽视了整体。
我的模型
写完上面的,自惭形秽。
- 每个点i拆成两个,中间连边,容量为ri,费用为0。即in(i)->out(i)。
- S->in(i),容量inf,费用为p。
- out(i)->in(i+m),i+m<=N,容量inf,费用为f。
- out(i)->in(i+n),i+n<=N,容量inf,费用s。
- out(i)->out(i+1),i< N,容量inf,费用0。
- out(N)->T,容量inf,费用为0。
我拆点不是看到了二分图,而是为了给节点赋容量。
对比两种模型,我的out很像二分图里的X,in很像二分图里的Y。实际上,用上下界网络流的方法,分离必要弧,建立附加源S’、汇T’