题面

数据范围看起来很像网络流诶(滚那

因为限制多而且强,数据范围也不大,我们考虑不直接求答案,而是转化为判定问题

可以发现第二个限制相对好满足,我们直接枚举这个限制就可以。具体来说是枚举所有行中的最大值$x$,然后下面那个式子移项就可以得到$a*tot>=b*x$,其中tot表示芯片的总数

然后发现第一个限制还是很强,不好满足。怎么办呢?正难则反,转化成补集的问题:先把所有能安的芯片都安了,然后扣出来合法的答案

那么现在我们要扣掉的芯片尽量少,同时还要先保证扣出来的结果合法,那考虑用最小费用最大流,用最大流的限制使得答案合法,用最小费用求答案

具体来说我们这样建图(下面再解释):

①把原图拆成行和列共n个点

②记录每行每列最多的芯片个数(包括已经有的和空位),从原点向一边连边,另一边向汇点连边(这里为了方便我默认原点向行连,汇点向列连)。容量为芯片个数,费用为零(这个不用解释吧)

③第i行向第i列连容量为我们枚举的答案的边,表示至多留下这些芯片,费用仍然为零

④对于每个空位(x,y),从第x行向第y列连流量为1费用为1的边,表示同时从这一行一列扣掉一个芯片

然后跑最小费用最大流,当且仅当最大流等于芯片的最大总数(包括已经有的和空位))时更新答案,为什么?

因为最小费用最大流会优先保证满流,所以我们③中连的边相当于限制了每行每列的芯片个数一样,就满足了第一个限制,然后扣掉的加上剩下的等于总数才是合法的,所以这时候更新答案

大概就是这样,我觉得这题还是有点意思的=。=

 #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int B=,N=,M=,inf=1e9;
int mxr[B],mxc[B],mapp[B][B]; char rd[B];
int mflw[N],mcst[N],pren[N],pree[N],queu[N];
int p[N],noww[*M],goal[*M],flow[*M],cost[*M];
int n,a,b,s,t,id,ocp,tot,num,cnt,ans,maxf,minc; queue<int> qs;
void Link(int f,int t,int v,int c)
{
noww[++cnt]=p[f],p[f]=cnt;
goal[cnt]=t,flow[cnt]=v,cost[cnt]=c;
noww[++cnt]=p[t],p[t]=cnt;
goal[cnt]=f,flow[cnt]=,cost[cnt]=-c;
}
void Setit()
{
memset(mxr,,sizeof mxr);
memset(mxc,,sizeof mxc);
ocp=tot=,ans=-,s=n*+,t=s+;
for(int i=;i<=n;i++)
{
scanf("%s",rd+);
for(int j=;j<=n;j++)
{
mapp[i][j]=rd[j],ocp+=rd[j]=='C';
if(rd[j]!='/') mxr[i]++,mxc[j]++,tot++;
}
}
}
void Init(int st,int ed)
{
memset(mflw,0x3f,sizeof mflw);
memset(mcst,0x3f,sizeof mcst);
memset(queu,,sizeof queu),pren[ed]=-;
qs.push(st),queu[st]=true,mcst[st]=;
}
bool SP(int st,int ed)
{
Init(st,ed);
while(!qs.empty())
{
int tn=qs.front();
qs.pop(),queu[tn]=false;
for(int i=p[tn],g;i;i=noww[i])
if(mcst[g=goal[i]]>mcst[tn]+cost[i]&&flow[i])
{
pree[g]=i,pren[g]=tn;
mcst[g]=mcst[tn]+cost[i];
mflw[g]=min(mflw[tn],flow[i]);
if(!queu[g]) qs.push(g),queu[g]=true;
}
}
return ~pren[ed];
}
void MCMF(int st,int ed)
{
while(SP(st,ed))
{
maxf+=mflw[ed],id=ed;
minc+=mflw[ed]*mcst[ed];
while(id!=st)
{
flow[pree[id]]-=mflw[ed];
flow[pree[id]^]+=mflw[ed];
id=pren[id];
}
}
}
int Solve(int x)
{
memset(p,,sizeof p),cnt=,maxf=minc=;
for(int i=;i<=n;i++)
Link(s,i,mxr[i],),Link(i+n,t,mxc[i],),Link(i,i+n,x,);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(mapp[i][j]=='.') Link(i,j+n,,); MCMF(s,t);
return maxf==tot?(a*(tot-minc)>=b*x?tot-ocp-minc:-):-;
}
int main()
{
while(scanf("%d%d%d",&n,&a,&b)!=EOF)
if(n||a||b)
{
Setit();
for(int i=;i<=n;i++)
ans=max(ans,Solve(i));
printf("Case %d: ",++num);
~ans?printf("%d\n",ans):printf("impossible\n");
}
else break;
return ;
}

解题:BZOJ 2673 World Final 2011 Chips Challenge的更多相关文章

  1. BZOJ 2440 [中山市选2011]完全平方数 | 莫比乌斯函数

    BZOJ 2440 [中山市选2011]完全平方数 | 莫比乌斯函数 题面 找出第k个不是平方数的倍数的数(1不是平方数, \(k \le 10^9\)). 题解 首先二分答案,问题就转化成了求\([ ...

  2. [2011WorldFinal]Chips Challenge[流量平衡]

    Chips Challenge Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  3. bzoj 2441 [中山市选2011]小W的问题

    bzoj 2441 [中山市选2011]小W的问题 Description 有一天,小W找了一个笛卡尔坐标系,并在上面选取了N个整点.他发现通过这些整点能够画出很多个"W"出来.具 ...

  4. 【BZOJ 2673】[Wf2011]Chips Challenge

    题目大意: 传送门 $n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A ...

  5. bzoj 3961: [WF2011]Chips Challenge【最小费用最大流】

    参考:https://blog.csdn.net/Quack_quack/article/details/50554032 神建图系列 首先把问题转为全填上,最少扣下来几个能符合条件 先考虑第2个条件 ...

  6. BZOJ 2440 [中山市选2011]完全平方数 (二分 + 莫比乌斯函数)

    2440: [中山市选2011]完全平方数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 4805  Solved: 2325[Submit][Sta ...

  7. BZOJ 2440: [中山市选2011]完全平方数 [容斥原理 莫比乌斯函数]

    2440: [中山市选2011]完全平方数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3028  Solved: 1460[Submit][Sta ...

  8. BZOJ 3721: PA2014 Final Bazarek

    3721: PA2014 Final Bazarek Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 645  Solved: 261[Submit][ ...

  9. [BZOJ 2440] [中山市选2011] 完全平方数 【二分 + 莫比乌斯函数】

    题目链接:BZOJ - 2440 题目分析 首先,通过打表之类的方法可以知道,答案不会超过 2 * k . 那么我们使用二分,对于一个二分的值 x ,求出 [1, x] 之间的可以送出的数有多少个. ...

随机推荐

  1. Hyperledger Fabric Ledger——账本总账

    Ledger Ledger(账本)即所有的state transitions(状态切换),是有序且不可篡改的.state transitions(状态切换)是由参与方提交的chaincode(智能合约 ...

  2. ossec安装

    安装 安装要求 对于Unix系统来说,OSSEC只需要GNU的make.gcc和libc.推荐使用OpenSSL,但仅属于一个可选项.而且,通常您只需在一个系统上做编译操作,然后将二进制程序复制到其他 ...

  3. 转载---LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别

    总是分不太清楚LIBRARY_PATH和LD_LIBRARY_PATH环境变量的区别,每次都是现查一下,转载到这里,备忘... 转载自:https://www.cnblogs.com/panfeng4 ...

  4. 在写ssh项目时浏览器页面出现http status 404 – not found

    HTTP Status 404 - /streetManager/index.jsp type Status report message /streetManager/index.jsp descr ...

  5. Task 4.4二维环形数组求最大子矩阵之和

    任务: (1)输入一个二维整形数组,数组里有正数也有负数. (2)二维数组首尾相接,象个一条首尾相接带子一样. (3)数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和. (4)求所有子数 ...

  6. Hibernate利用纯sql

    String hql = "select * from shop where shop.strid in(select strid from moneythreeshop where mon ...

  7. WebGL学习笔记(二)

    目录 绘制多个顶点 使用缓冲区对象 类型化数组 使用drawArrays()函数绘制图形 图形的移动 图形的旋转 图形的缩放 绘制多个顶点 使用缓冲区对象 创建缓冲区对象 var vertexBuff ...

  8. 微信小程序Mustache语法

    小程序开发的wxml里,用到了Mustache语法.所以,非常有必要把Mustache研究下. 什么是Mustache?Mustache是一个logic-less(轻逻辑)模板解析引擎,它是为了使用户 ...

  9. \0 的ASCII码值是多少

    \0 的ASCII码值是多少 #include<iostream> using namespace std; void main() { char c = '\0'; cout<&l ...

  10. 字符串经过base64编码后的长度与原字符串的长度是什么关系呀?

    beforeEncode为Encode之前的字符串 那么Encode后的字符串长度为: 1.如果beforeEncode.length()是3的整数倍,那么长度为  (beforeEncode.len ...