最小割解决最优值最突出的特点就是要将对象划分到两个集合中
这题很明显,裸的最小割
先把点连成一根根柱子,就是p(x,y,k)-->p(x,y,k+1)流量是P(x,y,k+1)的不和谐值
然后s与p(x,y,1)连边,流量是p(x,y,1)的不和谐值
最后再将p(x,y,r)都连向t
下面就是解决切割限制了,其实很简单,就是我们通过连边是不满足限制的点不构成一个割的方案
具体来说就是,对于任意p(x,y,k) (k<r) 连p(x',y',k+d)--->p(x,y,k) 流量inf,x',y'为邻居
画图可知正确性
1 const inf=200000007; 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 flow,next,point:longint; 7 end; 8 9 var edge:array[0..3000010] of node; 10 pre,p,cur,numh,h,d:array[0..64010] of longint; 11 num:array[0..40,0..40,0..40] of longint; 12 l,w,n,m,r,k,j,t,len,x,y,i: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 edge[len].point:=y; 23 edge[len].flow:=f; 24 edge[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 tmp,u,i,j,q,neck:longint; 36 begin 37 for i:=0 to t do 38 cur[i]:=p[i]; 39 numh[0]:=t+1; 40 neck:=inf; 41 u:=0; 42 sap:=0; 43 while h[0]<t+1 do 44 begin 45 d[u]:=neck; 46 i:=cur[u]; 47 while i<>-1 do 48 begin 49 j:=edge[i].point; 50 if (edge[i].flow>0) and (h[u]=h[j]+1) then 51 begin 52 pre[j]:=u; 53 cur[u]:=i; 54 neck:=min(neck,edge[i].flow); 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(edge[j].flow,neck); 64 inc(edge[j xor 1].flow,neck); 65 end; 66 neck:=inf; 67 end; 68 break; 69 end; 70 i:=edge[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 q:=-1; 77 tmp:=t; 78 i:=p[u]; 79 while i<>-1 do 80 begin 81 j:=edge[i].point; 82 if edge[i].flow>0 then 83 if h[j]<tmp then 84 begin 85 q:=i; 86 tmp:=h[j]; 87 end; 88 i:=edge[i].next; 89 end; 90 h[u]:=tmp+1; 91 inc(numh[h[u]]); 92 cur[u]:=q; 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,r); 106 readln(l); 107 t:=0; 108 for k:=1 to r do 109 for i:=1 to n do 110 for j:=1 to m do 111 begin 112 read(x); 113 inc(t); 114 num[k,i,j]:=t; 115 build(num[k-1,i,j],t,x); 116 end; 117 inc(t); 118 for i:=1 to n do 119 for j:=1 to m do 120 begin 121 build(num[r,i,j],t,inf); 122 for w:=1 to 4 do 123 begin 124 x:=i+dx[w]; 125 y:=j+dy[w]; 126 if (x>0) and (x<=n) and (y>0) and (y<=m) then 127 begin 128 for k:=1 to r-l do 129 build(num[k+l,x,y],num[k,i,j],inf); 130 end; 131 end; 132 end; 133 134 writeln(sap); 135 end.