https://darkbzoj.cf/problem/2673

有一个芯片,芯片上有N*N(1≤N≤40)个插槽,可以在里面装零件。

有些插槽不能装零件,有些插槽必须装零件,剩下的插槽随意。

要求装好之后满足如下两条要求:

1、第 i 行和第 i 列的零件数目必须一样多(1≤i≤N)。

2、第 i 行的零件数目不能超过总的零件数目的 A/B(1≤i≤N,0≤A≤B≤1000,B≠0)。

求最多可以另外放多少个零件(就是除掉必须放的)。如果无解输出impossible。

zkw费用流就是像跑最大流一样跑费用流,可以并行处理使得稠密图和二分图速度变快(据说)。

棋盘图依然是把横纵坐标拆成2n个点,每一个棋子可以用其横坐标到纵坐标的一条路表示。

棋盘上放最多的棋子相当于所有位置放上棋子后去掉最少的棋子,最小费用流处理就是给每一个可以去掉的棋子一个固定费用(1)。

i行和i列保留零件数目一样多就是从横坐标的i点到纵坐标的i点连一条费用为0流量固定为w的路。 w一定时,每一行每一列保留棋子的数量一定<=w。w上限是n所以我们可以枚举w建n次图跑网络流。

此时的最大流最小费用就是条件w下可以去掉的棋子数量的最小值(不仅要验证满足题目中的要求2,还要验证最大流=所有可以放棋子的位置的数量,因为保留棋子数量有时候可能小于某行列C的数量)(如果这个w跑最大流最小费用的方案不合法,那么就不存在w的合法条件)。

这个建n次图的方法有点像noip2017的那道搜索题目 NOIP2017 D2T2宝藏 都是按层次找的想法。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define LL long long
const int maxn=;
int n,A,B;
char ch[][];
int han[]={},shu[]={},sum,num,S,T,mx,cnt;
struct nod{
int x,y,next,v,co,rev;
}e[maxn];
int head[]={},tot=;
void init(int x,int y,int v,int co){
e[++tot].y=y;e[tot].x=x;e[tot].v=v;e[tot].co=co;e[tot].next=head[x];e[tot].rev=tot+;head[x]=tot;
e[++tot].y=x;e[tot].x=y;e[tot].v=;e[tot].co=-co;e[tot].next=head[y];e[tot].rev=tot-;head[y]=tot;
}
queue<int>q;
int dis[]={};bool vis[]={};
bool SPFA(){
memset(dis,,sizeof(dis));
memset(vis,,sizeof(vis));
mx=dis[];
q.push(S);vis[S]=;dis[S]=;
while(!q.empty()){
int x=q.front(),y;q.pop();vis[x]=;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(e[i].v>&&dis[y]>dis[x]+e[i].co){
dis[y]=dis[x]+e[i].co;
if(!vis[y]){
q.push(y);vis[y]=;
}
}
}
}
return dis[T]!=mx;
}
int dfs(int x,int val){
if(x==T){
cnt+=dis[T]*val;
return val;
}
int liu=,tv,y;vis[x]=;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(vis[y])continue;
if(e[i].v>&&dis[y]==dis[x]+e[i].co){
vis[y]=;
tv=dfs(y,min(val-liu,e[i].v));
liu+=tv;e[i].v-=tv;e[e[i].rev].v+=tv;
if(liu==val)break;
}
}
return liu;
}
int main(){
int C=;
while(~scanf("%d%d%d",&n,&A,&B)){
if(n==&&A==&&B==)break;
++C;
memset(han,,sizeof(han));memset(shu,,sizeof(shu));
sum=;cnt=;S=n*+;T=S+;
int zz=,ans=-;
for(int i=;i<n;i++){
scanf("%s",ch[i]);
for(int j=;j<n;j++){
if(ch[i][j]!='/'){
++han[i+];++shu[j+];++sum;
if(ch[i][j]=='C')++zz;
}
}
}
for(int w=;w<=n;w++){
tot=;memset(head,,sizeof(head));
for(int i=;i<=n;i++){
init(S,i,han[i],);
init(i+n,T,shu[i],);
init(i,i+n,w,);
for(int j=;j<=n;j++){
if(ch[i-][j-]=='.')init(i,j+n,,);
}
}int num=;cnt=;
while(SPFA()){memset(vis,,sizeof(vis));num+=dfs(S,sum);}
if(num==sum&&w*B<=(sum-cnt)*A)ans=max(ans,sum-cnt);
}cout<<endl;
if(ans==-)printf("Case %d: impossible\n",C);
else printf("Case %d: %d\n",C,ans-zz);
}
return ;
}

BZOJ2673 [Wf2011]Chips Challenge 费用流 zkw费用流 网络流的更多相关文章

  1. CSU 1948: 超级管理员(普通费用流&&zkw费用流)

    Description 长者对小明施加了膜法,使得小明每天起床就像马丁的早晨一样. 今天小明早上醒来发现自己成了一位仓管员.仓库可以被描述为一个n × m的网格,在每个网格上有几个箱子(可能没有).为 ...

  2. Bzoj2673 3961: [WF2011]Chips Challenge 费用流

    国际惯例题面:如果我们枚举放几个零件的话,第二个限制很容易解决,但是第一个怎么办?(好的,这么建图不可做)考虑我们枚举每行每列最多放几个零件t,然后计算零件总数sum.这样如果可行的话,则有t*B&l ...

  3. bzoj 3961: [WF2011]Chips Challenge【最小费用最大流】

    参考:https://blog.csdn.net/Quack_quack/article/details/50554032 神建图系列 首先把问题转为全填上,最少扣下来几个能符合条件 先考虑第2个条件 ...

  4. 【BZOJ 2673】[Wf2011]Chips Challenge

    题目大意: 传送门 $n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A ...

  5. bzoj3961[WF2011]Chips Challenge

    题意 给出一个n*n的网格,有些格子必须染成黑色,有些格子必须染成白色,其他格子可以染成黑色或者白色.要求最后第i行的黑格子数目等于第i列的黑格子数目,且某一行/列的格子数目不能超过格子总数的A/B. ...

  6. [Wf2011]Chips Challenge

    两个条件都不太好处理 每行放置的个数实际很小,枚举最多放x 但还是不好放 考虑所有位置先都放上,然后删除最少使得合法 为了凑所有的位置都考虑到,把它当最大流 但是删除最少,所以最小费用 行列相关,左行 ...

  7. zkw费用流+当前弧优化

    zkw费用流+当前弧优化 var o,v:..] of boolean; f,s,d,dis:..] of longint; next,p,c,w:..] of longint; i,j,k,l,y, ...

  8. 学习了ZKW费用流

    所谓ZKW费用流,其实就是Dinic. 若干年前有一个人发明了最小增广路算法,每次用BFS找一条增广路,时间O(nm^2) 然后被DinicD飞了:我们为什么不可以在长度不变时多路增广呢?时间O(n^ ...

  9. zkw费用流

    期末结束,竞赛生活继续开始,先怒刷完寒假作业再说 至于期末考试,数学跪惨,各种哦智障错,还有我初中常用的建系大法居然被自己抛至脑后,看来学的还是不扎实,以后数学要老老实实学.物理被永哥黑了两分,然后很 ...

随机推荐

  1. 【译】第三篇 Integration Services:增量加载-Adding Rows

    本篇文章是Integration Services系列的第三篇,详细内容请参考原文. 增量加载是什么增量加载仅加载与先前加载差异的.差异包括:->新增的行->更新的行->删除的行通过 ...

  2. node.js 基础篇

    日志输出方式 node test.js 2>error.log 1>info.log 如果需要日志文件追加 node test.js 2>>error.log 1>> ...

  3. MySQL防范SQL注入风险

    MySQL防范SQL注入风险 0.导读 在MySQL里,如何识别并且避免发生SQL注入风险 1.关于SQL注入 互联网很危险,信息及数据安全很重要,SQL注入是最常见的入侵手段之一,其技术门槛低.成本 ...

  4. python3 切换工作文件夹

    python3 默认的工作文件夹在Python安装路径下.如下为查看工作文件夹路径: >>> import os >>> os.getcwd() 'D:\\Work ...

  5. 虚拟机 CentOS7 64

    下载地址:https://www.centos.org/download/ 下载完后以后使用虚拟机安装即可

  6. 微信 JS API 支付教程

    最近一个项目中用到了微信开发,之前没有做过支付相关的东西,算是拿这个来练练手,刚开始接触支付时候很懵逼,加上微信支付开发文档本来就讲得不清楚,我是彻底蒙圈了,参考了很多代码之后,算是有一点思路了. 用 ...

  7. dedecms自定义模型之独立模型在首页、列表页、内容调用内容

    dedecms关于自定义模型(独立模型)的首页.列表页.内容怎么调用?在后台自定义模型(独立模型)的建立及自定义字段的添加比较简单,需要注意两点: (1)如果某个字段需要在前台列表页显示,则在前台参数 ...

  8. opencv(1)图像处理

    2.图像操作 图片裁剪 裁剪是利用array自身的下标截取实现 HSV空间 除了区域,图像本身的属性操作也非常多,比如可以通过HSV空间对色调和明暗进行调节.HSV空间是由美国的图形学专家A. R. ...

  9. mdb数据库文件如何导入Microsoft SQL Server 2008中

    1.在‘开始’菜单打开‘Microsoft SQL Server 2008→SQL Server Management Studio’. 2.新建一个数据库(名称自定义),选择新建的数据库点击右键选择 ...

  10. ZCTF2015 pwn试题分析

    ZCTF的pwn赛题分析, PWN100 这道题与SCTF的pwn100玩法是一样的,区别在于这个要过前面的几个限制条件.不能触发exit(0).否则就不能实现溢出了. 依然是触发canary来lea ...