对于这种题很容易看出是费用流吧……

但这道题不容易建模;

首先是怎么表示目标状态和其实状态,看起来有黑有白很复杂

但实际上,不难发现,白色格子没什么用,起决定作用的是黑格子

也就是我们可以把问题简化:我们怎么把开始的黑格子移到目标位置

但这个移动不是一般的移动;

在一条路径中,不难发现,起始两点是只要交换一次,其他路径上个点都是要交换2次

由于题目给出的限制是点的交换次数限制c,所以不难想到要拆点

但是平常的拆两点好像无法表示这个特征,

于是我们就拆成3个点……

p1--->p0--->p2

p1表示交换进来,p2表示交换出去;

所以不难得出:

对于每个点,如果它是原图中的黑点,连边<p1,p0,c/2,0>,<p0,p2,(c+1)/2,0>,<s,p0,1,0>;

如果它是新图中的黑点,连边<p1,p0,(c+1)/2>,<p0,p2,c/2,0>,<p0,t,1,0>;

注意存在有的点在新图原图都是黑点的情况(在这里WA了一次)

如果它在两个图中都是白点,那么连边<p1,p0,c/2,0>,<p0,p2,c/2,0>

最后对于原图中任意可达两点,连边<pi2,pj1,inf,1>

注意这道题可以交换对角线,还要判断是否可行,细节挺多

  1. const dx:array[..] of integer=(-,,,,,-,-,);
  2.       dy:array[..] of integer=(,,,-,,-,,-);
  3.       inf=;
  4. type node=record
  5.        next,point,cost,flow:longint;
  6.      end;
  7.  
  8. var edge:array[..] of node;
  9.     p,pre,cur,d:array[..] of longint;
  10.     v:array[..] of boolean;
  11.     a,b,c:array[..,..] of integer;
  12.     q:array[..] of longint;
  13.     ch,t,n,m,i,j,k,x,y,po,tot,sum,ans,len:longint;
  14.     s:string;
  15.  
  16. procedure add(x,y,f,w:longint);
  17.   begin
  18.     inc(len);
  19.     edge[len].point:=y;
  20.     edge[len].flow:=f;
  21.     edge[len].cost:=w;
  22.     edge[len].next:=p[x];
  23.     p[x]:=len;
  24.   end;
  25.  
  26. function spfa:boolean;
  27.   var i,x,y,f,r:longint;
  28.   begin
  29.     fillchar(v,sizeof(v),false);
  30.     v[]:=true;
  31.     for i:= to t do
  32.       d[i]:=inf;
  33.     d[]:=;
  34.     f:=;
  35.     r:=;
  36.     q[f]:=;
  37.     while f<=r do
  38.     begin
  39.       x:=q[f];
  40.       v[x]:=false;
  41.       i:=p[x];
  42.       while i<>- do
  43.       begin
  44.         y:=edge[i].point;
  45.         if edge[i].flow> then
  46.           if d[y]>d[x]+edge[i].cost then
  47.           begin
  48.             d[y]:=d[x]+edge[i].cost;
  49.             pre[y]:=x;
  50.             cur[y]:=i;
  51.             if not v[y] then
  52.             begin
  53.               inc(r);
  54.               q[r]:=y;
  55.               v[y]:=true;
  56.             end;
  57.           end;
  58.         i:=edge[i].next;
  59.       end;
  60.       inc(f);
  61.     end;
  62.     if d[t]=inf then exit(false) else exit(true);
  63.   end;
  64.  
  65. procedure mincost;
  66.   var i,j,neck:longint;
  67.   begin
  68.     while spfa do
  69.     begin
  70.       i:=t;
  71.       neck:=inf;
  72.       while i<> do
  73.       begin
  74.         j:=cur[i];
  75.         if neck>edge[j].flow then neck:=edge[j].flow;
  76.         i:=pre[i];
  77.       end;
  78.       i:=t;
  79.       while i<> do
  80.       begin
  81.         j:=cur[i];
  82.         dec(edge[j].flow,neck);
  83.         inc(edge[j xor ].flow,neck);
  84.         i:=pre[i];
  85.       end;
  86.       ans:=ans+d[t]*neck;
  87.       dec(ch,neck);
  88.       if ch= then break;
  89.     end;
  90.   end;
  91.  
  92. begin
  93.   readln(n,m);
  94.   len:=-;
  95.   fillchar(p,sizeof(p),);
  96.   t:=*n*m+;
  97.   for i:= to n do
  98.   begin
  99.     readln(s);
  100.     for j:= to m do
  101.     begin
  102.       a[i,j]:=ord(s[j])-;
  103.       tot:=tot+a[i,j];
  104.     end;
  105.   end;
  106.   for i:= to n do
  107.   begin
  108.     readln(s);
  109.     for j:= to m do
  110.     begin
  111.       b[i,j]:=ord(s[j])-;
  112.       sum:=sum+b[i,j];
  113.     end;
  114.   end;
  115.   for i:= to n do
  116.   begin
  117.     readln(s);
  118.     for j:= to m do
  119.       c[i,j]:=ord(s[j])-;
  120.   end;
  121.   if sum<>tot then
  122.   begin
  123.     writeln(-);
  124.     halt;
  125.   end
  126.   else ch:=sum;
  127.   sum:=n*m;
  128.   for i:= to n do
  129.   begin
  130.     for j:= to m do
  131.     begin
  132.       x:=(i-)*m+j;
  133.       if a[i,j]= then
  134.       begin
  135.         add(x+sum,x,c[i,j] shr ,);
  136.         add(x,x+sum,,);
  137.         add(x,x+*sum,(c[i,j]+) shr ,);
  138.         add(x+*sum,x,,);
  139.         add(,x,,);
  140.         add(x,,,);
  141.         if b[i,j]= then    //细节
  142.         begin
  143.           add(x,t,,);
  144.           add(t,x,,);
  145.         end;
  146.       end
  147.       else if b[i,j]= then
  148.       begin
  149.         add(x+sum,x,(c[i,j]+) shr ,);
  150.         add(x,x+sum,,);
  151.         add(x,x+*sum,c[i,j] shr ,);
  152.         add(x+*sum,x,,);
  153.         add(x,t,,);
  154.         add(t,x,,);
  155.       end
  156.       else if (a[i,j]+b[i,j]=) then
  157.       begin
  158.         add(x+sum,x,c[i,j] shr ,);
  159.         add(x,x+sum,,);
  160.         add(x,x+*sum,c[i,j] shr ,);
  161.         add(x+*sum,x,,);
  162.       end;
  163.     end;
  164.   end;
  165.  
  166.   for i:= to n do
  167.     for j:= to m do
  168.     begin
  169.       po:=(i-)*m+j;
  170.       for k:= to do
  171.       begin
  172.         x:=i+dx[k];
  173.         y:=j+dy[k];
  174.         if (x<=n) and (y<=m) and (x>) and (y>) then
  175.         begin
  176.           tot:=(x-)*m+y;
  177.           add(po+*sum,tot+sum,inf,);
  178.           add(tot+sum,po+*sum,,-);
  179.         end;
  180.       end;
  181.     end;
  182.   mincost;
  183.   if ch<> then writeln(-) else writeln(ans);
  184. end.

bzoj2668的更多相关文章

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

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

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

    题目链接 BZOJ2668 题解 容易想到由\(S\)向初始的黑点连边,由终态的黑点向\(T\)连边,然后相邻的点间连边 但是这样满足不了交换次数的限制,也无法计算答案 考虑如何满足一个点的交换次数限 ...

  3. 【BZOJ-2668】交换棋子 最小费用最大流

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

  4. BZOJ2668: [cqoi2012]交换棋子

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

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

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

  6. BZOJ2668:[CQOI2012]交换棋子(费用流)

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

  7. [CQOI2012][bzoj2668] 交换棋子 [费用流]

    题面 传送门 思路 抖机灵 一开始看到这题我以为是棋盘模型-_-|| 然而现实是骨感的 后来我尝试使用插头dp来交换,然后又惨死 最后我不得不把目光转向那个总能化腐朽为神奇的算法:网络流 思维 我们要 ...

  8. BZOJ2668: [cqoi2012]交换棋子(费用流)

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

  9. [bzoj2668] [洛谷P3159] [cqoi2012] 交换棋子

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

随机推荐

  1. CC2640-之功耗

    一.测量方式,以DEMO板测量,以消除其它外围不同造成的电流不同. 二.测量结果 以原厂simpleBLEperipheral工程为例 1.如果在低功耗模式下,+5DB发射,最小电流为1.66MA 2 ...

  2. Servlet一次乱码排查后的总结(转)

    原文地址:http://my.oschina.net/looly/blog/287255 由来 在写一个小小的表单提交功能的时候,出现了乱码,很奇怪request上来的参数全部是乱码,而从数据库查询出 ...

  3. 图像处理-07-图像的轮廓提取-Robert算子

    图像的轮廓提取-Robert算子 图像的边缘:周围像素灰度有阶跃变化或“屋顶”变化的那些像素的集合,边缘广泛存在于物体与背景之间.物体与物体之间,基元与基元之间,是图像分割的重要依据. 物体的边缘是由 ...

  4. Begin Andriod -- 安装android开发环境

    很久以前学过Andriod,现在已经忘的快没有了,重新捡起来练练,顺带写写博客,感受下写博的乐趣. 第一步:安装java jdk.jre(jdk:开发环境,jre:运行环境). (一)java jdk ...

  5. String类中的equals()方法

    在Java中,每一个对象都有一个地址空间,在这空间保存着这个对象的值. equals 比较的是值,==比较的地址以及值. 01: public class StringExample02: {03: ...

  6. 1187: [HNOI2007]神奇游乐园 - BZOJ

    Description 经历了一段艰辛的旅程后,主人公小P乘坐飞艇返回.在返回的途中,小P发现在漫无边际的沙漠中,有一块狭长的绿地特别显眼.往下仔细一看,才发现这是一个游乐场,专为旅途中疲惫的人设计. ...

  7. XCode6.1中的ios7.1适配

    在xcode6.1中新创建的项目,运行在我的ios7.1的ipod touch上时(与5s的一样的尺寸, Retina屏幕), 上下出现了黑边,由于没有下载7.1的模拟器,不知道模拟器上有无问题, 查 ...

  8. 你不需要jQuery(四)

    jQuery是个好东西.它诞生于IE6在互联网称霸的那个时代.jQuery的存在让我们的代码能很好的兼容各种平台. 然而,到如今,浏览器技术已经取得了巨大的进步.我们可以自由的使用所有最新众多ES5/ ...

  9. 【LCA】bzoj 2144:跳跳棋

    2144: 跳跳棋 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 248  Solved: 121[Submit][Status][Discuss] ...

  10. TIANKENG’s restaurant

    Problem B:http://codeforces.com/contest/616/problem/B B. Dinner with Emma 题意:一对夫妻要去餐厅吃晚饭,Emma 想去最豪华( ...