【BZOJ 2673】[Wf2011]Chips Challenge

时间:2023-01-17 23:05:47

题目大意:

  传送门

  $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&colon; &lbrack;CTSC2007&rsqb;数据备份Backup (贪心&plus;优先队列&plus;双向链表)

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

  2. Kruskal算法及其类似原理的应用——【BZOJ 3654】tree&amp&semi;&amp&semi;【BZOJ 3624】&lbrack;Apio2008&rsqb;免费道路

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

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

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

  4. LCA 【bzoj 4281】 &lbrack;ONTAK2015&rsqb;Zwi&aogon;zek Harcerstwa Bajtockiego

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

  5. 【BZOJ 3958】 3958&colon; &lbrack;WF2011&rsqb;Mummy Madness (二分&plus;扫描线、线段树)

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

  6. 【BZOJ 1191】 &lbrack;Apio2010&rsqb;特别行动队 (斜率优化)

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

  7. 【BZOJ 1096】 &lbrack;ZJOI2007&rsqb;仓库建设 (斜率优化)

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

  8. 【BZOJ 2132】圈地计划 &amp&semi;&amp&semi; 【7&period;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. C&num; 蓝牙编程

    C#进行蓝牙编程 本节我们给大家用源码的形式给大家介绍如何用C#调用蓝牙.下面的源码是基于destop的C#调用蓝牙的程序,也就是使用普通版本的.NET Framework来调用编程,一般是有蓝牙的笔 ...

  2. 绑定hosts

    测试过程中需绑定hosts.将测试环境IP绑定域名,输入域名即可连接到测试环境. 1  hosts文件地址:C:\WINDOWS\system32\drivers\etc 2  用记事本打开hosts ...

  3. 【转】MyBatis学习总结&lpar;二&rpar;——使用MyBatis对表执行CRUD操作

    [转]MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作 上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据, ...

  4. bzoj 1096&colon; &lbrack;ZJOI2007&rsqb;仓库建设

    dp是很好想的了,关键是数据太大,普通dp肯定超时,所以一定有用某种优化,dp优化也就那么几种,这道题用的是斜率优化,先写出普通的状态转移方程: dp[i] = min{  dp[j] + Σ ( p ...

  5. 不同浏览器创建XMLHttpRequest对象

    function getXHR() { if (XMLHttpRequest) { return new XMLHttpRequest(); } else { return new ActiveXOb ...

  6. 超赞网页背景效果-canvas-nest&period;js

    canvas-nest.js 是 canvas 上绘制的蜂窝状网站背景. 引入的时候的注意事项:js加载的时候需要保证body已经加载: 一个简单的demo: <!DOCTYPE html&gt ...

  7. Cracking The Coding Interview3&period;3

    //Imagine a (literal) stack of plates. If the stack gets too high, it might topple. Therefore, in re ...

  8. 暑假学习笔记(一)——初识Neo4j和APICloud入门

    暑假学习笔记(一)--初识Neo4j和APICloud入门 20180719笔记 1.Neo4j 接了学姐的系统测试报告任务,感觉工作很繁重,但是自己却每天挥霍时光.9月份就要提交系统测试报告了,但是 ...

  9. Java 程序员最喜欢的 11 款免费 IDE 编辑器

    Java开发人员需要花费大量的时间埋头于Java代码中,使用各种不同的IDE(Intergrated Development Environment)来开发Java代码,所以下面我将为大家介绍11个不 ...

  10. ionic2——apk签名

    1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序,我们需要对我们发布的APK文件进行唯一签名,保证我们每次发布的版本 ...