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

看到选取显然最小割

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

注意每个点的收益获得条件是[或],因此我们考虑拆点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

 

posted on 2015-05-18 19:04  acphile  阅读(622)  评论(0编辑  收藏  举报