• bzoj3774


    这算是最小割中比较难的吧

    看到选取显然最小割

    看到上下左右四个点我感觉肯定和染色相关

    注意每个点的收益获得条件是[或],因此我们考虑拆点i', i,分别表示通过四周控制和控制本身的代价

    连边s-->i 流量为选择该点的代价; i-->i' 流量为该点的收益; i'到上下左右的j,流量为正无穷,表示另一个条件

    这样,要获得收益便一定要割断一边,就满足了或的性质

    注意,另一种颜色的连边与这种颜色相反,由于染色可以得到二分图

    所以另一种颜色的连边反过来建即可

      1 const inf=1000000007;
      2       dx:array[1..4] of longint=(0,0,-1,1);
      3       dy:array[1..4] of longint=(1,-1,0,0);
      4  
      5 type node=record
      6        po,next,flow:longint;
      7      end;
      8  
      9 var e:array[0..2000010] of node;
     10     numh,h,cur,p,pre,d:array[0..5010] of longint;
     11     a:array[0..51,0..51] of longint;
     12     ans,i,j,x,y,len,t,n,m,k:longint;
     13  
     14 function min(a,b:longint):longint;
     15   begin
     16     if a>b then exit(b) else exit(a);
     17   end;
     18  
     19 procedure add(x,y,f:longint);
     20   begin
     21     inc(len);
     22     e[len].po:=y;
     23     e[len].flow:=f;
     24     e[len].next:=p[x];
     25     p[x]:=len;
     26   end;
     27  
     28 procedure build(x,y,f:longint);
     29   begin
     30     add(x,y,f);
     31     add(y,x,0);
     32   end;
     33  
     34 function sap:longint;
     35   var i,j,u,neck,tmp,q:longint;
     36   begin
     37     for i:=0 to t do
     38       cur[i]:=p[i];
     39     sap:=0;
     40     u:=0;
     41     neck:=inf;
     42     numh[0]:=t+1;
     43     while h[0]<t+1 do
     44     begin
     45       i:=cur[u];
     46       d[u]:=neck;
     47       while i<>-1 do
     48       begin
     49         j:=e[i].po;
     50         if (e[i].flow>0) and (h[u]=h[j]+1) then
     51         begin
     52           neck:=min(neck,e[i].flow);
     53           pre[j]:=u;
     54           cur[u]:=i;
     55           u:=j;
     56           if u=t then
     57           begin
     58             sap:=sap+neck;
     59             while u<>0 do
     60             begin
     61               u:=pre[u];
     62               j:=cur[u];
     63               dec(e[j].flow,neck);
     64               inc(e[j xor 1].flow,neck);
     65             end;
     66             neck:=inf;
     67           end;
     68           break;
     69         end;
     70         i:=e[i].next;
     71       end;
     72       if i=-1 then
     73       begin
     74         dec(numh[h[u]]);
     75         if numh[h[u]]=0 then exit;
     76         tmp:=t;
     77         q:=-1;
     78         i:=p[u];
     79         while i<>-1 do
     80         begin
     81           j:=e[i].po;
     82           if e[i].flow>0 then
     83             if h[j]<tmp then
     84             begin
     85               tmp:=h[j];
     86               q:=i;
     87             end;
     88           i:=e[i].next;
     89         end;
     90         cur[u]:=q;
     91         h[u]:=tmp+1;
     92         inc(numh[h[u]]);
     93         if u<>0 then
     94         begin
     95           u:=pre[u];
     96           neck:=d[u];
     97         end;
     98       end;
     99     end;
    100   end;
    101  
    102 begin
    103   len:=-1;
    104   fillchar(p,sizeof(p),255);
    105   readln(n,m);
    106   t:=2*n*m+1;
    107   for i:=1 to n do
    108     for j:=1 to m do
    109     begin
    110       read(x);
    111       inc(k); a[i,j]:=k;
    112       if (i+j) mod 2=1 then build(0,a[i,j],x)
    113       else build(a[i,j],t,x);
    114     end;
    115  
    116   for i:=1 to n do
    117     for j:=1 to m do
    118     begin
    119       read(x);
    120       ans:=ans+x;
    121       if (i+j) mod 2=1 then build(a[i,j],a[i,j]+n*m,x)
    122       else build(a[i,j]+n*m,a[i,j],x);
    123     end;
    124  
    125   for i:=1 to n do
    126     for j:=1 to m do
    127     begin
    128       if (i+j) mod 2=1 then
    129       begin
    130         for k:=1 to 4 do
    131         begin
    132           x:=i+dx[k];
    133           y:=j+dy[k];
    134           if (x<=0) or (x>n) or (y<=0) or (y>m) then continue;
    135           build(a[i,j]+n*m,a[x,y],inf);
    136         end;
    137       end
    138       else begin
    139         for k:=1 to 4 do
    140         begin
    141           x:=i+dx[k];
    142           y:=j+dy[k];
    143           if (x<=0) or (x>n) or (y<=0) or (y>m) then continue;
    144           build(a[x,y],a[i,j]+n*m,inf);
    145         end;
    146       end;
    147     end;
    148  
    149   writeln(ans-sap);
    150 end.
    View Code
  • 相关阅读:
    尾递归
    gcc/g++ 命令
    GCC输出带C源代码的汇编文件
    linux下Ctrl命令组合
    静态链接库(lib)、动态链接库(dll)与动态链接库的导入库(lib)
    VS2010-MFC(菜单:菜单及CMenu类的使用)
    VS2010-MFC(菜单:VS2010菜单资源详解)
    VS2010-MFC(常用控件:标签控件Tab Control 下)
    VS2010-MFC(常用控件:标签控件Tab Control 上)
    VS2010-MFC(常用控件:树形控件Tree Control 下)
  • 原文地址:https://www.cnblogs.com/phile/p/4512830.html
Copyright © 2020-2023  润新知