这算是最小割中比较难的吧
看到选取显然最小割
看到上下左右四个点我感觉肯定和染色相关
注意每个点的收益获得条件是[或],因此我们考虑拆点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.