题面

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

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

可以发现第二个限制相对好满足,我们直接枚举这个限制就可以。具体来说是枚举所有行中的最大值$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. Flink BLOB架构

    Flink中支持的BLOB文件类型 jar包 被user classloader使用的jar包 高负荷RPC消息 1. RPC消息长度超出了akka.framesize的大小 2. 在HA摸式中,利用 ...

  2. 【python 2.7】输入任意字母数字,输出其对应的莫尔斯码并播放声音

    #python 2.7 #!/usr/bin/env python # -*- coding:utf-8 -*- import os import winsound,sys,time __author ...

  3. 2019第十届蓝桥杯 E题 迷宫

    /*输入 30 50 01010101001011001001010110010110100100001000101010 00001000100000101010010000100000001001 ...

  4. 04-matplotlib-柱形图

    import numpy as np import matplotlib.pyplot as plt # 柱形图 # 例一 N =5 y = [15,28,10,30,25] index = np.a ...

  5. 字幕字体滚动插件——scroxt.js

    README scroxt.js Overview scroxt.js是一个字体滚动的插件库,包括视频弹幕滚动,直播弹幕.直播弹幕强制模式.单行水平左右滚动.文本垂直滚动上下,用于简单快捷生成滚动字体 ...

  6. Notes of Daily Scrum Meeting(11.10)

    Notes of Daily Scrum Meeting(11.10) 今天是周一,虽然仍然在假期里,但是我们仍然要继续我们团队的开发工作了,分工大家已然都很明确,所以接下来 就是认真投入,把自己负责 ...

  7. b5

    吴晓晖(组长) 过去两天完成了哪些任务 完善推荐算法 展示GitHub当日代码/文档签入记录 接下来的计划 推荐算法 还剩下哪些任务 组员:刘帅珍 过去两天完成了哪些任务: 修改原型,整理背景 明日计 ...

  8. java小学生四则运算带面板版 但我不知道为什么同类变量却进不了动作监听中去

    ---恢复内容开始--- package yun; import java.util.*; import java.awt.*; import java.awt.event.ActionEvent; ...

  9. 第一次spring冲刺第6天

    鉴于昨天的调查,今天做了个谈论,主要针对以下几个问题 1.我们的客户类型? 2.如何实现他们的需求? 3.他们真正想要什么? 4.如何保证他们的满足度? 5.怎么使得工程不陷入死循环? 6.还存在什么 ...

  10. 注册表:DWORD

    百度百科 DWORD全称Double Word,是指注册表的键值,每个word为2个字节的长度,DWORD 双字即为4个字节,每个字节是8位,共32位. 在键值项窗口空白处单击右键,选择“新建”菜单项 ...