最小割解决最优值最突出的特点就是要将对象划分到两个集合中
这题很明显,裸的最小割
先把点连成一根根柱子,就是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.
View Code

 

posted on 2015-03-17 20:22  acphile  阅读(184)  评论(0编辑  收藏  举报