Bzoj2673 3961: [WF2011]Chips Challenge 费用流
国际惯例题面:
如果我们枚举放几个零件的话,第二个限制很容易解决,但是第一个怎么办?(好的,这么建图不可做)
考虑我们枚举每行每列最多放几个零件t,然后计算零件总数sum。这样如果可行的话,则有t*B<=sum*A。
考虑第一个限制怎么办。我们可以钦定所有可行的位置都放上零件,然后再把多的零件拆下来。
我们令sxi为第i行能放的最多零件数,syi为第i列能放的最多零件数。
由源点向每一行连流量sxi费用0的边,每一列向汇点连流量syi费用0的边。
然后让每一行i向每一列i连流量t费用0的边,表示第i行和第j列最多同时不拆(留下)t个零件。
最后对于所有输入为'.'的格子ij,由第i行向第j列连容量1费用1的边,表示拆下第i行第j列的零件。
跑费用流,必须满流才满足题意(零件要么行和列同时留下,要么拆掉),费用表示拆掉的零件个数。
然后用留下的零件个数和t去比较是否合法,计算答案就行了。
感觉这题就是给了我们一种网络流建图,补集转化的姿势(如果选择的流量行列不移动统一,那么去掉的流量是否统一?如果选择的不好限制,去掉的是否容易限制?)
代码:
#pragma GCC optimize(2)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
const int maxn=1e2+1e1,maxe=maxn*maxn;
const int inf=0x3f3f3f3f; char in[maxn][maxn];
int s[maxn],t[maxe<<],nxt[maxe<<],f[maxe<<],c[maxe<<],cnt;
int dis[maxn],inq[maxn],ins[maxn],st,ed,cst;
int sx[maxn],sy[maxn],su,ini;
int n,A,B,ans; inline void coredge(int from,int to,int flow,int cost) {
t[++cnt] = to , f[cnt] = flow , c[cnt] = cost ,
nxt[cnt] = s[from] , s[from] = cnt;
}
inline void singledge(int from,int to,int flow,int cost) {
coredge(from,to,flow,cost) , coredge(to,from,,-cost);
}
inline bool spfa() {
memset(dis,0x3f,sizeof(dis)) , dis[st] = ;
std::queue<int> q; q.push(st) , inq[st] = ;
while( q.size() ) {
const int pos = q.front(); q.pop() , inq[pos] = ;
for(int at=s[pos];at;at=nxt[at])
if( f[at] && dis[t[at]] > dis[pos] + c[at] ) {
dis[t[at]] = dis[pos] + c[at];
if( !inq[t[at]] ) q.push(t[at]) , inq[t[at]] = ;
}
}
return dis[ed] != inf;
}
inline int dfs(int pos,int flow) {
if( pos == ed ) return flow;
int ret = , now = ; ins[pos] = ;
for(int at=s[pos];at;at=nxt[at])
if( f[at] && !ins[t[at]] && dis[t[at]] == dis[pos] + c[at] ) {
now = dfs(t[at],std::min(flow,f[at])) ,
ret += now , flow -= now , cst += c[at] * now ,
f[at] -= now , f[at^] += now;
if( !flow ) return ins[pos] = , ret;
}
if( !ret ) dis[pos] = inf;
return ins[pos] = , ret;
}
inline int flow() { // we must got full flow .
int ret = , now = ;
while( spfa() ) while( ( now = dfs(st,inf) ) ) ret += now;
return ret;
} inline void build(int t) {
memset(s,,sizeof(s)) , cnt = , st = n * + , ed = st + , cst = ;
#define cov(x,id) (x*2-1+id)
for(int i=;i<=n;i++) {
singledge(st,cov(i,),sx[i],) ,
singledge(cov(i,),cov(i,),t,) ,
singledge(cov(i,),ed,sy[i],) ;
}
for(int i=;i<=n;i++) for(int j=;j<=n;j++) if( in[i][j] == '.' ) singledge(cov(i,),cov(j,),,);
}
inline int calc(int t) {
build(t);
if( flow() != su ) return -; // illegal .
int used = su - cst;
return used * A >= t * B ? used - ini : -;
} int main() {
static int cse;
while( scanf("%d%d%d",&n,&A,&B) == && ( n || A || B ) ) {
memset(sx,,sizeof(sx)) , memset(sy,,sizeof(sy)) , ini = su = , ans = -;
for(int i=;i<=n;i++) {
scanf("%s",in[i]+);
for(int j=;j<=n;j++){
if( in[i][j] != '/' ) ++sx[i] , ++sy[j] , ++su;
ini += in[i][j] == 'C';
}
}
for(int i=;i<=n;i++) ans = std::max( ans , calc(i) );
printf("Case %d: ",++cse);
if( !~ans ) puts("impossible");
else printf("%d\n",ans);
}
return ;
}
(话说我都多路增广+码内O2了才卡到332MS,那几个几十MS过掉的是怎么做到的)
華やかな 煌びやかな運命を
做着拥有绚烂命运的梦
夢見て 泣いた夜は
却因为这样的梦 止不住泪水
银色の流星も泣いている
银色的流星也在哭泣
ナツシスに向けて
向着水仙花海
あっけなく さよならを告げぬよう
不想轻易说出再见
唇が 告げぬように
所以咬紧双唇
呟きに星空も木霊する
唯有轻声细语回响在星空下
ナツシスに向けて
朝着水仙
いつまでも届け
将它传递到永远
Bzoj2673 3961: [WF2011]Chips Challenge 费用流的更多相关文章
- BZOJ2673 [Wf2011]Chips Challenge 费用流 zkw费用流 网络流
https://darkbzoj.cf/problem/2673 有一个芯片,芯片上有N*N(1≤N≤40)个插槽,可以在里面装零件. 有些插槽不能装零件,有些插槽必须装零件,剩下的插槽随意. 要求装 ...
- bzoj 3961: [WF2011]Chips Challenge【最小费用最大流】
参考:https://blog.csdn.net/Quack_quack/article/details/50554032 神建图系列 首先把问题转为全填上,最少扣下来几个能符合条件 先考虑第2个条件 ...
- bzoj3961[WF2011]Chips Challenge
题意 给出一个n*n的网格,有些格子必须染成黑色,有些格子必须染成白色,其他格子可以染成黑色或者白色.要求最后第i行的黑格子数目等于第i列的黑格子数目,且某一行/列的格子数目不能超过格子总数的A/B. ...
- [Wf2011]Chips Challenge
两个条件都不太好处理 每行放置的个数实际很小,枚举最多放x 但还是不好放 考虑所有位置先都放上,然后删除最少使得合法 为了凑所有的位置都考虑到,把它当最大流 但是删除最少,所以最小费用 行列相关,左行 ...
- 【BZOJ 2673】[Wf2011]Chips Challenge
题目大意: 传送门 $n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A ...
- 【UVALive - 5131】Chips Challenge(上下界循环费用流)
Description A prominent microprocessor company has enlisted your help to lay out some interchangeabl ...
- 【BZOJ3502/2288】PA2012 Tanie linie/【POJ Challenge】生日礼物 堆+链表(模拟费用流)
[BZOJ3502]PA2012 Tanie linie Description n个数字,求不相交的总和最大的最多k个连续子序列. 1<= k<= N<= 1000000. Sam ...
- Day5费用流
算法 zkw费用流:多路增广,增光D[y]=D[i]+c的边 无源汇上下界最小费用可行流 每次强行增加下界的流量 类似网络流,拆边 原边的费用为c,拆出来的边费用为0 负边和负圈 直接应用 SDOI2 ...
- hdu-5988 Coding Contest(费用流)
题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
随机推荐
- C语言拼接字符串 -- 使用strcat()函数
[头文件]#include <string.h> [原型] char *strcat(char *dest, const char *src); [参数]: dest 为目标字符串指针,s ...
- 对HUAWEI-ManagedProvisioning的一次不完整分析
分析思路 关注点1:AndroidManifest.xml是Android应用的入口文件,包含有APP服务的权限.广播和启动位置. 关注点2:涉及到修改系统的函数,setWifiEnabled().I ...
- .net active up mail 邮件发送
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- 用python查看windows事件日志的方法(待后续研究)
#coding=utf8 import copy import ctypes from ctypes import byref, POINTER, cast, c_uint64, c_ulong, c ...
- centos环境无法安装paramiko的问题解决
yum install openssl-devel yum install pycrypto yum install python-devel 全部安装完毕后执行pip install paramik ...
- C#实现图片叠加,图片上嵌入文字,文字生成图片的方法
/// <summary> /// 图片叠加 /// </summary> /// <param name="sender"& ...
- WebRTC服务器——Licode 环境搭建
WebRTC服务器--Licode 环境搭建 系统配置 阿里云服务器 Ubuntu 14.04.5 LTS Docker 环境搭建 在一台空的机器上搭建docker环境,先要安装docker,执行下面 ...
- (并发编程)进程 (multiprocessing--Process实现进程并发)
['创建进程2方式种', '进程对象属性:join方法,守护进程obj.daemon=True,obj.pid, obj.name, obj.terminate(),obj.is_alive()等 ' ...
- 使用linux计划任务自动拉起停止的通达OA服务apache和mysql服务
概述: 数据库或web服务器瞬时并发过大时,可能面临宕机的危险,用类似开门狗的程序自动监控程序是否正常运行,在服务停止时自动启动服务,可临时解决该问题 监控apache服务的脚本: 每两分钟执行脚本检 ...
- Oracle常用sql语句(一)
# Sql的分类 # DDL (Data Definition Language):数据定义语言,用来定义数据库对象:库.表.列等: CREATE. ALTER.DROP DML(Data Manip ...