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 ...
随机推荐
- UDP template 代码
服务端 from socket import * import json,struct client= socket(AF_INET,SOCK_STREAM) client.connect(('127 ...
- ios 侧边手势滑动返回 禁用/开启 功能
// 禁用 返回手势 if ([self.navigationController respondsToSelector:@selector(interactivePopGestureR ...
- VM 安装 linux Enterprise_R5_U4_Server_I386_DVD教程图解
ocp 学习笔记 20161126--------linux 笔记整理 一:安装linux系统环境: 1:linux 系统安装包下载路径:链接:链接: https://pan.baidu.com/s/ ...
- 洛谷 P4427 求和
传送门啦 思路: 开始不肿么容易想到用倍增,但是想到需要求 $ Lca $ ,倍增这种常数小而且快的方法就很方便了.求 $ Lca $ 就是一个最普通的板子.那现在考虑怎么求题目中的结果. 树上差分可 ...
- Best quotes from The Vampire Diary(《吸血鬼日记》经典台词)
1. I will start fresh, be someone new. 1. 我要重新开始,做不一样的自己. 2. It's the only way I'll make it through. ...
- window 连linux
https://blog.csdn.net/ruanjianruanjianruan/article/details/46954681 https://blog.csdn.net/u013754317 ...
- PHP中的一些常用函数
<?php //===============================时间日期=============================== //y返回年最后两位,Y年四位数,m月份数字 ...
- poj1177 矩形周长并
线段树扫描线的模板题,一个月前写的发现忘了一些还是要看看以前的博客呀! /* 思路:数据小不用离散化处理,线段树叶子结点维护一个区间 */ #include<iostream> #incl ...
- iOS学习笔记之UITableViewController&UITableView
iOS学习笔记之UITableViewController&UITableView 写在前面 上个月末到现在一直都在忙实验室的事情,与导师讨论之后,发现目前在实验室完成的工作还不足以写成毕业论 ...
- 用switch语句判断月份,打印出当前月份所在的季节
var today=new Date(); var abc=today.getMonth(); switch (abc) { case 0: case 1: case 2: document.writ ...