BZOJ 2668 交换棋子(费用流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2668
题意:有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子中的棋子,最终达到目标状态。要求第i行第j列的格子只能参与m[i,j]次交换。
思路: 我们将1看做要移动的数字,将0看做空白。那么若1在始末状态个数不同则无解;如某个格子始末状态均有1则这个格子的1对结果无影响,可以将其都置为0。将每个格子拆为为个点p0,p1,p2:
(1)若格子初始为1,则连边:<s,p0,1,0>,<p1,p0,m[i][j]/2,0)>,<p0,p2,(m[i][j]+1)/2,0>;
(2)若格子末状态为0,则连边:<p0,t,1,0>,<p1,p0,(m[i][j]+1)/2,0>,<p0,p2,m[i][j]/2,0>;
(3)始末都是空白,则连边:<p1,p0,m[i][j]/2,0>,<p0,p2,m[i][j]/2,0>;
(4)相邻格子x和y连边<px2,py1,INF,0>。
struct node
{
int u,v,next,cost,cap;
};
node edges[N];
int head[N],e;
void add(int u,int v,int cap,int cost)
{
edges[e].u=u;
edges[e].v=v;
edges[e].cap=cap;
edges[e].cost=cost;
edges[e].next=head[u];
head[u]=e++;
}
void Add(int u,int v,int cap,int cost)
{
add(u,v,cap,cost);
add(v,u,0,-cost);
}
int pre[N],F[N],C[N],visit[N];
int SPFA(int s,int t,int n)
{
int i;
for(i=0;i<=n;i++) F[i]=0,C[i]=INF,visit[i]=0;
queue<int> Q;
Q.push(s); F[s]=INF; C[s]=0;
int u,v,cost,cap;
while(!Q.empty())
{
u=Q.front();
Q.pop();
visit[u]=0;
for(i=head[u];i!=-1;i=edges[i].next)
{
if(edges[i].cap>0)
{
v=edges[i].v;
cost=edges[i].cost;
cap=edges[i].cap;
if(C[v]>C[u]+cost)
{
C[v]=C[u]+cost;
F[v]=min(F[u],cap);
pre[v]=i;
if(!visit[v]) visit[v]=1,Q.push(v);
}
}
}
}
return F[t];
}
char a[25][25],b[25][25],c[25][25];
int d[25][25][3];
int dx[]={-1,-1,-1,0,1,1,1,0};
int dy[]={-1,0,1,1,1,0,-1,-1};
int n,m,s,t,cnt;
int ans;
int MCMF(int s,int t,int n)
{
int i,x,temp,M=0;
while(temp=SPFA(s,t,n))
{
M+=temp;
for(i=t;i!=s;i=edges[pre[i]].u)
{
x=pre[i];
ans+=edges[x].cost*temp;
edges[x].cap-=temp;
edges[x^1].cap+=temp;
}
}
return M==cnt;
}
int main()
{
RD(n,m);
int i,j;
FOR1(i,n) RD(a[i]+1);
FOR1(i,n) RD(b[i]+1);
FOR1(i,n) RD(c[i]+1);
int k=0;
FOR1(i,n) FOR1(j,m)
{
a[i][j]-='0';
b[i][j]-='0';
c[i][j]-='0';
d[i][j][0]=++k;
d[i][j][1]=++k;
d[i][j][2]=++k;
if(a[i][j]&&b[i][j]) a[i][j]=0,b[i][j]=0;
}
s=0; t=++k;
clr(head,-1);
cnt=0;
int x,y,p=0;
FOR1(i,n) FOR1(j,m)
{
if(a[i][j])
{
cnt++;
Add(s,d[i][j][0],1,0);
Add(d[i][j][1],d[i][j][0],c[i][j]/2,0);
Add(d[i][j][0],d[i][j][2],(c[i][j]+1)/2,0);
}
else if(b[i][j])
{
p++;
Add(d[i][j][0],t,1,0);
Add(d[i][j][1],d[i][j][0],(c[i][j]+1)/2,0);
Add(d[i][j][0],d[i][j][2],c[i][j]/2,0);
}
else
{
Add(d[i][j][1],d[i][j][0],c[i][j]/2,0);
Add(d[i][j][0],d[i][j][2],c[i][j]/2,0);
}
FOR0(k,8)
{
x=i+dx[k];
y=j+dy[k];
if(x>=1&&x<=n&&y>=1&&y<=m)
{
Add(d[i][j][2],d[x][y][1],INF,1);
}
}
}
if(cnt!=p||!MCMF(s,t,t+1)) puts("-1");
else PR(ans);
}
BZOJ 2668 交换棋子(费用流)的更多相关文章
- 【BZOJ2668】[cqoi2012]交换棋子 费用流
[BZOJ2668][cqoi2012]交换棋子 Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列 ...
- BZOJ2668: [cqoi2012]交换棋子(费用流)
Description 有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Input 第一行 ...
- [BZOJ 2668] 交换棋子
Link: BZOJ 2668 传送门 Solution: 重点在于对于每条转移路径:首尾算一次,中间节点算两次 可以一点拆三点,将原流量拆成入流量和出流量 但其实也可以就拆两点,分前后是否是一首尾点 ...
- BZOJ.2668.[CQOI2012]交换棋子(费用流zkw)
题目链接 首先黑白棋子的交换等价于黑棋子在白格子图上移动,都到达指定位置. 在这假设我们知道这题用网络流做. 那么黑棋到指定位置就是一条路径,考虑怎么用流模拟出这条路径. 我们发现除了路径的起点和终点 ...
- [CQOI2012] 交换棋子 - 费用流
有一个n行m列的黑白棋盘,你每次可以交换两个相邻格子(相邻是指有公共边或公共顶点)中的棋子,最终达到目标状态.要求第i行第j列的格子只能参与mi,j次交换. Solution 一个点拆三份,入点,主点 ...
- [CQOI2012][bzoj2668] 交换棋子 [费用流]
题面 传送门 思路 抖机灵 一开始看到这题我以为是棋盘模型-_-|| 然而现实是骨感的 后来我尝试使用插头dp来交换,然后又惨死 最后我不得不把目光转向那个总能化腐朽为神奇的算法:网络流 思维 我们要 ...
- [bzoj 1449] 球队收益(费用流)
[bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...
- BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)
BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...
- bzoj 1070: [SCOI2007]修车 费用流
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 2785 Solved: 1110[Submit][Status] ...
随机推荐
- mongodb子文档查询
--子文档分页 -- 测试数据 db.childTests.insert({ "_id" : 1, "item" : "ABC", &quo ...
- 在ASP.NET非MVC环境中(WebForm中)构造MVC的URL参数
目前项目中有个需求,需要在WebForm中去构造MVC的URL信息,这里写了一个帮助类可以在ASP.NET非MVC环境中(WebForm中)构造MVC的URL信息,主要就是借助当前Http上下文去构造 ...
- onTouch和onTouchEvent
public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null && mOnTo ...
- HDU4288:Coder(线段树单点更新版 && 暴力版)
Problem Description In mathematics and computer science, an algorithm describes a set of procedures ...
- 视频处理控件TVideoGrabber中如何混合多个视频源(1)
其实一个或是几个作为普通的视频源使用的TVideoGrabber组件,可以进行混合来作为一个TVideoGrabber组件使用,这些普通的组件可以是视频捕捉设备或是视频剪辑等.同时这个混合的组件独立于 ...
- android 应用架构随笔三(ListView)
import java.util.ArrayList; import java.util.List; import com.heima.googleplay.holder.BaseHolder; im ...
- python使用装饰器捕获异常
可以编写一个通用的捕获异常的装饰器, 当程序发生异常时可以继续执行后续动作. 尤其适合于使用大量断言的验证性程序. 装饰器的实现原理使用了回调技术. 如下所示, robust 是一个装饰器. 当在普通 ...
- ch1:python3 查看版本号、安装目录和工作空间目录
查看python版本: 每次打开python顶端会显示版本号 在程序中判断版本号可以通过import sys sys.version 在dos下可以通过python -V查看 安装目录:C:\Pyt ...
- Apache服务器访问过慢分析及解决
起因:线上的一台服务器,最近总是出现 访问 很慢的情况发生,点击一个链接要2秒钟以上才能打开,按照我们对于访问人数的估计,服务器应该不至于响应这么慢,从而需要针对这个问题进行分析,来解决网站访问过慢. ...
- maven打包异常:软件包com.sun.org.apache.xml.internal.security.utils.Base64 不存在
maven打包异常:软件包com.sun.org.apache.xml.internal.security.utils.Base64 不存在 将jre/lib/rt.jar添加到maven的compi ...