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. python——脚本和print

    脚本和print 1.脚本文件 <Python 基础教程>(第二版)中 P118页,原操作为下: 1 _metaclass_ = type 2 3 class Person: 4 def ...

  2. Framebuffer 驱动学习总结(二)---- Framebuffer模块初始化

    ---恢复内容开始--- Framebuffer模块初始化过程:--driver\video\fbmem.c 1.  初始化Framebuffer: FrameBuffer驱动是以模块的形式注册到系统 ...

  3. 二十、springboot之jpa开发@MappedSuperclass 注解说明

    @MappedSuperclass使用条件: 当我们进行开发项目时,我们经常会用到实体映射到数据库表的操作,此时我们经常会发现在我们需要映射的几个实体类中,有几个共同的属性,例如编号ID,创建者,创建 ...

  4. Gradle设置代理

    在本地仓库路径下(如果没有修改的话默认C:\Users\用户名\.gradle),或者项目下,新建一个文件gradle.properties systemProp.http.proxyHost=网址 ...

  5. Ubuntu 18.04安装MongoDB 4.0(社区版)

    Ubuntu 18.04(虚拟机VirtualBox上),MongoDB 4.0, 听室友说,23点有世界杯决赛呢!可是,孤要写博文的啊!以记录这忙乱的下午和晚间成功安装了一个软件到Linux上.—— ...

  6. python网络编程-进程锁

    一:进程锁的作用 进程锁是防止多进程并发执行在屏幕打印的时候,其他进程也输出数据到屏幕,而出现混乱现象. 比如:进程池中很多进程会向同一个日志文件中打印日志 二:代码 # -*- coding:utf ...

  7. ASP .NET Core 2.0 MVC 发布到 IIS 上以后 无法下载apk等格式的文件

    ASP .NET Core MVC 发布到  IIS 上以后 无法下载apk等格式的文件 使用.NET Core MVC创建了一个站点,其他文件可以下载,但是后来又需求,就把手机端的apk合适的文件上 ...

  8. 如何查看页面是否开启了gzip压缩

    1.谷歌浏览器 F12 2.在表头单击鼠标右键 3.如果开启了gzip则显示gzip,没有则是空

  9. SNMP相关命令

    SNMP的相关命令使用方法: snmpdelta 一直监视SNMP变量中的变化 linux:~ # snmpdelta -c public -v 1 -Cs -CT localhost IF-MIB: ...

  10. 洛谷P2458 保安站岗

    传送门啦 分析: 树形dp刚刚入门,这是我做的第一个一个点同时受父亲节点和儿子节点控制的题目. 由于这个题中某一个点放不放保安与父亲和儿子都有关系(因为线段的两个端点嘛),所以我们做题时就要考虑全面. ...