题面

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

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

可以发现第二个限制相对好满足,我们直接枚举这个限制就可以。具体来说是枚举所有行中的最大值$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. Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化

    Netty源码分析第一章:  Server启动流程 概述: 本章主要讲解server启动的关键步骤, 读者只需要了解server启动的大概逻辑, 知道关键的步骤在哪个类执行即可, 并不需要了解每一步的 ...

  2. 如何通过阿里云APP进行域名备案?阿里云备案流程需要多久?

    如何通过阿里云APP进行域名备案? 1.准备备案材料(很多初次使用阿里云APP进行备案的同学会问备案需要准备哪些资料,不二版本下面就给大家一一列举出来) 个人备案需要材料: ⑴<用户网站备案授权 ...

  3. DataRow对象的RowState和DataRowVersion属性特点

    DataRow对象有两个比较重要的属性,分别是行状态(RowState)和行版本(DataRowVersion),通过这两个属性能够有效的管理表中的行.下面简要的介绍一下行状态和行版本的特点和关系. ...

  4. Teamproject --人员职责

    职责分配: 初步分工如下: PM:林豪森 Dev:宋天舒 张迎春 黄漠源 刘翔宇 叶露婷 旦增晋美 黄敬博 Test:林豪森 宋天舒 张迎春 刘翔宇 经过团队的讨论,认为对于职责的分配,并不存在绝对的 ...

  5. No.1100_第九次团队会议

    在今天项目有了新的突破,大家的情绪明显高涨了一些,一改往日的颓丧.但是仍然还有很多功能没有完善,于是大家相互交流了一下自己的进度,列出还没有完善的部分,有些困难的部分一时解决不了,我们决定多人合作来解 ...

  6. java实验三 敏捷开发与XP实践

    一.实验内容 (一)敏捷开发与XP 软件开发流程的目的是为了提高软件开发.运营.维护的效率,并提高软件的质量.用户满意度.可靠性和软件的可维护性. 光有各种流程的思想是不够的,我们还要有一系列的工具来 ...

  7. 2018-2019-20172321 《Java软件结构与数据结构》第六周学习总结

    2018-2019-20172321 <Java软件结构与数据结构>第六周学习总结 教材学习内容总结 第10章 树 10.1概述 树由一个包含结点和边的集构成,其中的元素被储存在这些结点中 ...

  8. JAVA异常架构图及常见面试题

    红色为检查异常,就是eclipse要提示你是try catch 还是throws. 非检查异常,就是/0,nullpointexception,数据越界访问indexOfOutBounds 异常 错误 ...

  9. \0 的ASCII码值是多少

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

  10. java.time 时间和简单任务

    java.time是jdk1.8才用的 时间管理 package com.test.time; import java.time.*; /** * Created by MY on 2017/8/7. ...