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. 命名实体识别(NER)

    一.任务 Named Entity Recognition,简称NER.主要用于提取时间.地点.人物.组织机构名. 二.应用 知识图谱.情感分析.机器翻译.对话问答系统都有应用.比如,需要利用命名实体 ...

  2. SolrJ案例实现搭建环境——(十五)

    案例

  3. 【NOI题解】【bzoj题解】NOI2008 bzoj1063 道路设计

    @ACMLCZH学长出的毒瘤题T3.再也不是“善良”的出题人了. 题意:bzoj. 题解: 经典的树形DP题目,屡见不鲜了,然而我还是没有写出来. 这一类的题目有很多,例如这里的C题. 主要套路是把对 ...

  4. git fetch 命令

    git fetch命令用于从另一个存储库下载对象和引用. 使用语法 git fetch [<options>] [<repository> [<refspec>…] ...

  5. 【hihocoder1251】Today is a rainy day

    #include<bits/stdc++.h> ; ; const int inf=0x3f3f3f3f; using namespace std; char s1[N],s2[N]; ] ...

  6. HTML5学习--SVG全攻略(基础篇)

    明天高级篇 一.什么是SVG? SVG 指的是可伸缩矢量图形 (Scalable Vector Graphics),它用来定义用于网络的基于矢量的图形,使用 XML 格式定义图形.SVG 图像在放大或 ...

  7. Win10搜索不能用

    使用win10进行搜索时,一直显示win10特色的滚动条,但就是检索不出东西,我的主要是检索不到windows的内容: (个人感觉使用win10检索网页内容不太专业,就关闭了Web搜索) 最后有发现网 ...

  8. Unix IPC之Posix消息队列(2)

    /* Query status and attributes of message queue MQDES. */ extern int mq_getattr (mqd_t __mqdes, stru ...

  9. Linux命令之远程登录与执行远程主机命令

    实现远程登录的命令 ssh.telnet.rlogin (1)ssh命令 ssh命令是openssh套件中的客户端连接工具,可以给予ssh加密协议实现安全的远程登录服务器.ssh命令用于远程登录上Li ...

  10. Oracle 提示符

    http://blog.csdn.net/wyzxg/article/details/5647905