题目大意:

  传送门

  $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的更多相关文章

  1. 【BZOJ 1150】 1150: [CTSC2007]数据备份Backup (贪心+优先队列+双向链表)

    1150: [CTSC2007]数据备份Backup Description 你在一家 IT 公司为大型写字楼或办公楼(offices)的计算机数据做备份.然而数据备份的工作是枯燥乏味 的,因此你想设 ...

  2. Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&&【BZOJ 3624】[Apio2008]免费道路

    首先让我们来介绍Krukal算法,他是一种用来求解最小生成树问题的算法,首先把边按边权排序,然后贪心得从最小开始往大里取,只要那个边的两端点暂时还没有在一个联通块里,我们就把他相连,只要这个图里存在最 ...

  3. 【BZOJ 2957】楼房重建&&Codechef COT5 Count on a Treap&&【NOIP模拟赛】Weed 线段树的分治维护

    线段树是一种作用于静态区间上的数据结构,可以高效查询连续区间和单点,类似于一种静态的分治.他最迷人的地方在于“lazy标记”,对于lazy标记一般随我们从父区间进入子区间而下传,最终给到叶子节点,但还 ...

  4. LCA 【bzoj 4281】 [ONTAK2015]Związek Harcerstwa Bajtockiego

    [bzoj 4281] [ONTAK2015]Związek Harcerstwa Bajtockiego Description 给定一棵有n个点的无根树,相邻的点之间的距离为1,一开始你位于m点. ...

  5. 【BZOJ 3958】 3958: [WF2011]Mummy Madness (二分+扫描线、线段树)

    3958: [WF2011]Mummy Madness Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 96  Solved: 41 Descripti ...

  6. 【BZOJ 1191】 [Apio2010]特别行动队 (斜率优化)

    dsy1911: [Apio2010]特别行动队 [题目描述] 有n个数,分成连续的若干段,每段的分数为a*x^2+b*x+c(a,b,c是给出的常数),其中x为该段的各个数的和.求如何分才能使得各个 ...

  7. 【BZOJ 1096】 [ZJOI2007]仓库建设 (斜率优化)

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3940  Solved: 1736 Description ...

  8. 【BZOJ 2132】圈地计划 && 【7.22Test】计划

    两种版本的题面 Description 最近房地产商GDOI(Group of Dumbbells Or Idiots)从NOI(Nuts Old Idiots)手中得到了一块开发土地.据了解,这块土 ...

  9. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

随机推荐

  1. poi excel 常用操作

    基本 Workbook wb= new HSSFWorkbook(); Sheet sheet = wb.createSheet("sheetName"); Row row = s ...

  2. subsets(子集)

    Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solut ...

  3. scons脚本示例

    import os def list_dir(dir): all_dirs = [] for root, dirs, files in os.walk('./', True): for name in ...

  4. python---haproxy---文件操作

    haproxy 文件操作,操作属于简单操作,不复杂 # -*- coding:utf-8 -*- # LC def search(*args): #查找Haproxy文件中的服务器 list1 = [ ...

  5. Java 代码重用:操作与上下文重用

    目录 操作重用 参数化操作 上下文重用 上下文作为模板方法 结束语 我几乎不需要讨论为什么重用代码是有利的.代码重用(通常)会导致更快的开发与更少的 BUG.一旦一段代码被封装和重用,那么检查程序是否 ...

  6. 一个简单的小小记账本程序(java)

    感觉基础知识学了不少,但是一直搞不清一个项目的实际开发流程,所以就借着这个小记账本的程序梳理一下.因为楼主也是出于学习阶段的菜鸟,所以程序可能会有各种玄学的bug,希望一起提升吧. 跟着站长学到了很多 ...

  7. Django入门二之模板语法

    一. 模板变量 Context传入的可以是一个str,dict,list,甚至是一个实例对象 在html中如何调用这些对象进行取值呢 1. 变量名 {{ variable }} 返回字符串,无论是st ...

  8. Hello Django

    首先安装Django: 1.cmd界面,输入"pip3 install django" 2.输入"django-admin help",如下图表示安装成功   ...

  9. Docker 多主机网络总结(非常全)

    PS:文章首发公众号,欢迎大家关注我的公众号:aCloudDeveloper,专注技术分享,努力打造干货分享平台,二维码在文末可以扫,谢谢大家. 上篇文章介绍了容器网络的单主机网络,本文将进一步介绍多 ...

  10. HTML结构及基础语法

    一.HTML结构 <!DOCTYPE html><html lang="en"><head> <meta charset="UT ...