2668: [cqoi2012]交换棋子

Time Limit: 3 Sec  Memory Limit: 128 MB
Submit: 1334  Solved: 518
[Submit][Status][Discuss]

Description

有一个nm列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与mi,j次交换。

Input

第一行包含两个整数nm(1<=n, m<=20)。以下n行为初始状态,每行为一个包含m个字符的01串,其中0表示黑色棋子,1表示白色棋子。以下n行为目标状态,格式同初始状态。以下n行每行为一个包含m个0~9数字的字符串,表示每个格子参与交换的次数上限。
 

Output

输出仅一行,为最小交换总次数。如果无解,输出-1。

Sample Input

3 3
110
000
001
000
110
100
222
222
222

Sample Output

4

HINT

 

Source

 

[Submit][Status][Discuss]

HOME
Back


 

费用流,建图神建图。。。

照例说建图,看上去貌似毫无头绪,然而实际上还是可做的,首先可以看到有一个步数上限,自然就往网络流那边想,然后求最小交换的步数,应该貌似看上去是求一个最小费用,所以费用流。

首先自然是要拆点,比较特殊的是,这个题一个点拆三个点。。。。我们分别叫他们x,y,z,首先先从源点向所有是一的y点连一条容量为1,免费的边,从y点向汇点也这么连。然后对于这两张图,如果第一张图中有棋子,那么就连v[i][j]/2从x到y,(v[i][j]+1)/2从y到z,如果只是第二张图里有,那么就换换加一。最后把所有能互相影响的点从z到x连无限流0费的边,一遍费用流即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define ll long long
#define inf 500000000
#define re register
#define id ((i-1)*m+j)
using namespace std;
struct po
{
int from,to,dis,nxt,w;
}edge[];
int head[],dep[],n,m,s,t,u,num=-,x,y,l,tot,sum,k,fa[];
int dis[],b[],xb[],flow[];
char map1[][],map2[][],mapn[][],cnt;
int dx[]={,-,-,-,,,,,};
int dy[]={,-,,,,,,-,-};
inline long long read()
{
long long x=,c=;
char ch=' ';
while((ch<''||ch>'')&&ch!='-')ch=getchar();
while(ch=='-')c*=-,ch=getchar();
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*c;
}
inline void add_edge(int from,int to,int w,int dis)
{
edge[++num].nxt=head[from];
edge[num].to=to;
edge[num].w=w;
edge[num].dis=dis;
head[from]=num;
}
inline void add(int from,int to,int w,int dis)
{
add_edge(from,to,w,dis);
add_edge(to,from,,-dis);
}
inline bool spfa()
{
memset(b,,sizeof(b));
for(re int i=;i<=t;i++)
dis[i]=inf;
deque<int> q;
b[t]=;dis[t]=;
q.push_back(t);
while(!q.empty())
{
int u=q.front();
q.pop_front();
b[u]=;
for(re int i=head[u];i!=-;i=edge[i].nxt)
{
int v=edge[i].to;
if(edge[i^].w>&&dis[v]>dis[u]-edge[i].dis)
{
dis[v]=dis[u]-edge[i].dis;
if(!b[v])
{
b[v]=;
if(!q.empty()&&dis[v]>dis[q.front()])
q.push_front(v);
else
q.push_back(v);
}
}
}
}
return dis[s]<inf;
}
inline int dfs(int u,int low)
{
if(u==t)
{
b[t]=;
return low;
}
int diss=;
b[u]=;
for(re int i=head[u];i!=-;i=edge[i].nxt)
{
int v=edge[i].to;
if(!b[v]&&edge[i].w!=&&dis[v]==dis[u]-edge[i].dis)
{
int check=dfs(v,min(low,edge[i].w));
if(check>)
{
tot+=check*edge[i].dis;
low-=check;
diss+=check;
edge[i].w-=check;
edge[i^].w+=check;
if(low==) break;
}
}
}
return diss;
}
inline int max_flow()
{
int ans=;
while(spfa())
{
b[t]=;
while(b[t])
{
memset(b,,sizeof(b));
ans+=dfs(s,inf);
}
}
return ans;
}
int main()
{
memset(head,-,sizeof(head));
n=read();m=read();
s=;t=n*m*+;
int N=n*m;
for(re int i=;i<=n;i++)
for(re int j=;j<=m;j++){
cin>>map1[i][j];
if(map1[i][j]=='') add(s,id+N,,),cnt++;
}
for(re int i=;i<=n;i++)
for(re int j=;j<=m;j++){
cin>>map2[i][j];
if(map2[i][j]=='') add(id+N,t,,);
}
for(re int i=;i<=n;i++)
for(re int j=;j<=m;j++)
cin>>mapn[i][j];
for(re int i=;i<=n;i++)
for(re int j=;j<=m;j++){
if(map1[i][j]==map2[i][j]==''){
add(id,id+N,(mapn[i][j]-'')/,);add(id+N,id+N+N,(mapn[i][j]-'')/,);
}else if(map1[i][j]==''){
add(id,id+N,(mapn[i][j]-'')/,);add(id+N,id+N+N,(mapn[i][j]+-'')/,);
}else if(map2[i][j]==''){
add(id,id+N,(mapn[i][j]+-'')/,);add(id+N,id+N+N,(mapn[i][j]-'')/,);
}else add(id,id+N,(mapn[i][j]-'')/,),add(id+N,id+N+N,(mapn[i][j]-'')/,);
for(re int k=;k<=;k++){
int lx=dx[k]+i; int ly=dy[k]+j;
if(lx>=&&lx<=n&&ly>=&&ly<=m){
add(id+N+N,(lx-)*m+ly,inf,);
}
}
}
sum=max_flow();
if(sum>=cnt) cout<<tot;
else cout<<"-1";
}

[cqoi2012]交换棋子的更多相关文章

  1. BZOJ2668: [cqoi2012]交换棋子

    题解: 可以戳这里:http://www.cnblogs.com/zig-zag/archive/2013/04/21/3033485.html 其实自己yy一下就知道这样建图的正确性了. 感觉太神奇 ...

  2. BZOJ 2668: [cqoi2012]交换棋子

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1112  Solved: 409[Submit][Status ...

  3. 【BZOJ2668】[cqoi2012]交换棋子 费用流

    [BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...

  4. 洛谷 P3159(BZOJ 2668)[CQOI2012]交换棋子

    有一个\(n\)行\(m\)列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第\(i\)行第\(j\)列的格子只能参与\(m[i][j]\)次交换 ...

  5. P3159 [CQOI2012]交换棋子

    思路 相当神奇的费用流拆点模型 最开始我想到把交换黑色棋子看成一个流流动的过程,流从一个节点流向另一个节点就是交换两个节点,然后把一个位置拆成两个点限制流量,然后就有了这样的建图方法 S向所有初始是黑 ...

  6. BZOJ.2668.[CQOI2012]交换棋子(费用流zkw)

    题目链接 首先黑白棋子的交换等价于黑棋子在白格子图上移动,都到达指定位置. 在这假设我们知道这题用网络流做. 那么黑棋到指定位置就是一条路径,考虑怎么用流模拟出这条路径. 我们发现除了路径的起点和终点 ...

  7. 2668: [cqoi2012]交换棋子

    Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...

  8. [CQOI2012]交换棋子 网络流

    ---题面--- 题解: 一开始很快想出了一个接近正解的建图方法,但其实是错误的,不过还是骗了70分_(:зゝ∠)_ 首先我们可以观察到棋子有限,但费用多种,其实也就相当于限制了流量,找最小费用 对于 ...

  9. BZOJ2668:[CQOI2012]交换棋子——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2668 https://www.luogu.org/problemnew/show/P3159#sub ...

随机推荐

  1. LR测试文件上传

    开启fiddler  录制,回放,把上传文件放入脚本根目录中.

  2. OKhttp3

    针对上一博文订单调用用户使用默认数据交互方式,下面介绍下使用 Okhttp3网络数据交换方式. 1.订单启动类变化 package com.tycoon.orderService; import or ...

  3. encodeURI() 函数概述

    encodeURI() 函数的作用是将URI中的某些特定的字符以一位到四位的转义序列来替代,这些转义序列就是这些字符的UTF-8编码(如果说某些字符是由两个代替字符构成的,该字符也只会是四位的转义序列 ...

  4. jmeter对响应结果做正则、json、xpath结果测试

    上面的返回结果可用于关联取值测试 具体用法详见http://www.cnblogs.com/xinjing-jingxin/p/8554338.html http://goessner.net/art ...

  5. Linux 常用命令缩写及对应的

    0.项目名: Linux -- LINUs' uniX (开个玩笑不是这样的,别当真) GNU -- Gnu is Not Unix1.目录名: /boot:顾名思义 /root :同上 /run:同 ...

  6. 《UNIX网络编程》 -- 第五章

    str_cli 和 str_echo 函数 需要先弄清楚 3.9 readn.writen 和 readline 函数 str_cli void str_cli(FILE *fp, int sockf ...

  7. API网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd API 网关出现的原因

    API网关性能比较:NGINX vs. ZUUL vs. Spring Cloud Gateway vs. Linkerd http://www.infoq.com/cn/articles/compa ...

  8. [NOIP2018PJ]摆渡车

    [NOIP2018PJ]摆渡车 luogu mdPJ组这么难,还好考的TG组 先按t排序 设f[i][j]表示前i个人,第i个人等j分钟的最小总等待时间 这里j是小于2m的 可以考虑最坏情况下,一个人 ...

  9. 如何在Pycharm设置ES6语法环境

    首先 如果不进行相关设置就刚ES6 语法的话,会出现下面提示性错误(运行还是能正常出效果的): (let 飘红, 这只是其中之一, 其他语法也会飘红) 接着,就是解决问题: 首先打开设置: 接着找到下 ...

  10. php 使用sendmail发送邮件

    php 使用sendmail发送邮件 1.配置php.ini SMTP=smtp.163.com sendmail_from = 17760273453@163.com sendmail_path = ...