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 ...
随机推荐
- LOJ 3089: 洛谷 P5319: 「BJOI2019」奥术神杖
题目传送门:LOJ #3089. 题意简述: 有一个长度为 \(n\) 的母串,其中某些位置已固定,另一些位置可以任意填. 同时给定 \(m\) 个小串,第 \(i\) 个为 \(S_i\),所有位置 ...
- python中对列表和循环使用的小练习
#author devilf product_list = [ (), (), (), (), () ] shop_list = [] salary = input('pls enter your s ...
- tomcat6和tomcat7管理用户manager配置
tomcat用户登录文件配置 如果想要对部署在tomcat上的项目进行管理查看,需要在tomcat安装目录conf文件夹下的tomcat-user.xml里添加用户登录权限.具体添加的内容如下: To ...
- 02-第一个JavaScript代码
在页面中,我们可以在body标签中放入<script type=”text/javascript”></script>标签对儿,<script type=”text/ja ...
- hdu4190 二分答案
/*二分答案即可*/ #include<bits/stdc++.h> #define maxn 500005 #define ll long long #define INF 500000 ...
- poj2464扫描线好题,树状数组解法
用树状数组解比线段树快了好多,难度也下降许多 分别用两个树状数组维护当前扫描线左侧和右侧的点,离散化y轴即可 #include<iostream> #include<cstring& ...
- zoj3299 线段树区间更新,坐标建立线段树的方式
/* 平台和砖块的坐标离散化,边缘坐标转换成单位长度 处理下落信息,sum数组维护区间的砖块数量 把平台按高度从高到低排序,询问平台区间的砖块有多少,询问后将该区域砖块数置0 */ #include& ...
- .Net开发工程师工具箱
Visual Studio Visual Studio Productivity Power tool:Visual Studio专业版(及以上)的扩展,具有丰富的功能,如快速查找,导航解决方案,可搜 ...
- LINQ学习之旅(二)
一:查询表达式(LINQ)简介 LINQ是Language Integrated Query的简称,它是集成在.NET编程语言中的一种特性.已成为编程语言的一个组成部分,在编写程序时可以得到很好的编译 ...
- 基于OSGI.NET的MVC插件式开发
最近在研究OSGI.NET插件式开发框架.官方网站提供了一个基于OSGI.NET的插件仓库.下载官方的SDK包安装后VS项目模板会多出一组iOpenWorks项目模板.在学习过程中,发现通过iOpen ...