【BZOJ 2673】[Wf2011]Chips Challenge
题目大意:
$n*n$的棋盘,有一些位置可以放棋子,有一些已经放了棋子,有一些什么都没有,也不能放,要求放置以后满足:第i行和第i列的棋子数相同,同时每行的棋子数占总数比例小于$\frac{A}{B}$。求最多可以放多少,无解则输出$impossible$。
题解:
Orz一发大佬——传送门。
先把整张图放满,题目就转化为最少删多少点就合法。
我们用$numx$来记录每行可以放的和已经放棋子总数,$numy$记录每列。从$S$向第i行连流量为$numx_i$的0费用边,从第j列向$T$连流量为$numy_j$的边。先不考虑怎么构建中间的图,在不考虑$\frac{A}{B}$的情况,我们需要判断流量合法的,我们可以让到$T$的边都满流意味着选了和没选的可以构成全集。
我们对于可以放棋子的地方$(x,y)$,由第$x$行到第$y$列连$flow=1,cost=1$的边,表示将这个点删去的所需价值。
考虑后一个限制。
我们可以枚举每一行最多放置的棋子个数$f$,然后我们从第$i$行向第$i$列连一条$flow=f,cost=0$的边。表示第i行选了最多保留$f$个棋子,第$i$列保留棋子等同于这条边的流量,因为其他连向第$i$列的边都是要费用的,对第$i$行来讲其他的出边也是要费用的,而那些要费用的边就是删去的集合。
然后判断一下当前解是否合法即可。
代码:
#include "bits/stdc++.h"
using namespace std;
#define inf 0x3f3f3f3f
inline int read() {
int s=,k=;char ch=getchar ();
while (ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while (ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
}
const int N=;
struct edges {
int v,cap,cost;edges *pair,*last;
}edge[N*N],*head[N];int cnt;
inline void push(int u,int v,int cap,int cost) {
edge[++cnt]=(edges){v,cap,cost,edge+cnt+,head[u]},head[u]=edge+cnt;
edge[++cnt]=(edges){u,,-cost,edge+cnt-,head[v]},head[v]=edge+cnt;
}
int S,T,n,fl,ans;
int piS,vis[N];
int cost;
inline int aug(int x,int w) {
if (x==T) return cost+=1ll*piS*w,fl+=w,w;
vis[x]=true;
int ret=;
for (edges *i=head[x];i;i=i->last)
if (i->cap&&!i->cost&&!vis[i->v]) {
int flow=aug(i->v,min(i->cap,w));
i->cap-=flow,i->pair->cap+=flow,ret+=flow,w-=flow;
if (!w) break;
}
return ret;
}
inline bool modlabel() {
static int d[N];
memset(d,0x3f,sizeof d);d[T]=;
static deque<int> q;q.push_back(T);
int dt;
while (!q.empty()) {
int x=q.front();q.pop_front();
for (edges *i=head[x];i;i=i->last)
if (i->pair->cap&&(dt=d[x]-i->cost)<d[i->v])
(d[i->v]=dt)<=d[q.size()?q.front():]
?q.push_front(i->v):q.push_back(i->v);
}
for (int i=S;i<=T;++i)
for (edges *j=head[i];j;j=j->last)
j->cost+=d[j->v]-d[i];
piS+=d[S];
return d[S]<inf;
}
inline void solve() {
piS = cost = ;
while(modlabel())
do memset(vis,,sizeof vis);
while(aug(S, inf));
}
char mp[N][N];
int numx[N],numy[N],A,B;
int main() {
n=read(),A=read(),B=read();
T=n<<|;
int used=,sum=;
ans=-;
for (int i=;i<=n;++i) {
scanf("%s",mp[i]+);
for (int j=;j<=n;++j)
if(mp[i][j]=='C'||mp[i][j]=='.') {
++sum,++numx[i],++numy[j];
used+=mp[i][j]=='C';
}
}
for (int flow=;flow<=n;++flow) {
memset(head,,sizeof head);
cnt=;fl=;
for (int i=;i<=n;++i) {
push(S,i,numx[i],);
push(i+n,T,numy[i],);
push(i,i+n,flow,);
for (int j=;j<=n;++j)
if(mp[i][j]=='.')
push(i,j+n,,);
}
solve();
if (fl==sum&&flow*B<=(sum-cost)*A)
ans=max(ans,sum-cost);
}
if (ans==-) puts("impossible");
else printf("%d\n",ans-used);
}
【BZOJ 2673】[Wf2011]Chips Challenge的更多相关文章
- 【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列+双向链表)
1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设 ...
- Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&&【BZOJ 3624】[Apio2008]免费道路
首先让我们来介绍Krukal算法,他是一种用来求解最小生成树问题的算法,首先把边按边权排序,然后贪心得从最小开始往大里取,只要那个边的两端点暂时还没有在一个联通块里,我们就把他相连,只要这个图里存在最 ...
- 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护
线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...
- LCA 【bzoj 4281】 [ONTAK2015]Związek Harcerstwa Bajtockiego
[bzoj 4281] [ONTAK2015]Związek Harcerstwa Bajtockiego Description 给定一棵有n个点的无根树,相邻的点之间的距离为1,一开始你位于m点. ...
- 【BZOJ 3958】 3958: [WF2011]Mummy Madness (二分+扫描线、线段树)
3958: [WF2011]Mummy Madness Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 96 Solved: 41 Descripti ...
- 【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)
dsy1911: [Apio2010]特别行动队 [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个 ...
- 【BZOJ 1096】 [ZJOI2007]仓库建设 (斜率优化)
1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3940 Solved: 1736 Description ...
- 【BZOJ 2132】圈地计划 && 【7.22Test】计划
两种版本的题面 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土 ...
- -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】
[把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...
随机推荐
- python 字典dict类型合并(不能错过哦)
我要的字典的键值有些是数据库中表的字段名, 但是有些却不是, 我需要把它们整合到一起, 因此有些这篇文章.(非得凑够150个字,我也是没有办法,扯一点昨天的问题吧,话说python中的session就 ...
- WPF如何得到一个在用户控件内部的元素的坐标位置
例如有这样一个用户控件: <UserControl d:DesignHeight="100" d:DesignWidth="200" ...> &l ...
- miniUI中弹出框问题
---恢复内容开始--- 设置页面弹出框并提交弹出框内容 弹出按钮 <a class="btn_color_1" onclick="onEdit(0)"& ...
- Day9 基于TCP的套接字和基于UDP的套接字
服务端: ss=socket() #创建服务器套接字 ss.bind() #把地址绑定到套接字 ss.listen() #监听套接字, inf_loop: #服务器无限循环 cs=ss.accept( ...
- Day 网络协议介绍 简单通信的实现
比如说实现两个手机之间的通信,需要做的几部: 服务端: 1,买手机 2,插卡 3,开机 4,等电话链接 5,基于建立的链接,收发协议 6,挂电话 7,关机 import socket #买手机 pho ...
- RPi:QT+wiringPi demo程序
一个项目里面要用到这玩意儿,网上查了几篇文章凑出来最后还是不行,自己灵机一动就成了. 今天再次搜索的时候,发现另一篇文章已经讲明白了,真是欲哭无泪 程序大部分参考的是之前学qt的摸索出来的,其实只要在 ...
- Entity Framework分页扩展
Entity Framework分页在我初入门时总是困扰这我,无论是SQL分页还是Entity Framework的分页,总是显得那么麻烦,因此对于Entity Framework单独封装了分页. 一 ...
- MySQL的日志(二):事务日志
本文目录:1.redo log 1.1 redo log和二进制日志的区别 1.2 redo log的基本概念 1.3 日志块(log block) 1.4 log group和redo log fi ...
- SOFA 源码分析 — 调用方式
前言 SOFARPC 提供了多种调用方式满足不同的场景. 例如,同步阻塞调用:异步 future 调用,Callback 回调调用,Oneway 调用. 每种调用模式都有对应的场景.类似于单进程中的调 ...
- Oracle知识梳理(三)操作篇:SQL基础操作汇总
Oracle知识梳理(三)操作篇:SQL基础操作汇总 一.表操作 1.表的创建(CREATE TABLE): 基本语句格式: CREATE TABLE table_name ( col_ ...