首先不难发现海拔高度只能为0或1

因为决策是单调的

不难发现最优决策一定是划分为海拔为0和1两块,不会出现01相间的情况

所以这很明显是一个最小割

由于n*n很大,我们必须要用平面图最小割转化为最短路径

在我们做1001时,是平面无向图,这里是平面有向图,其实是一样的

只要记住以起点终点为对角线划分外面为两个面,然后以面为点,边两侧面连边

最后注意新图的任意一条路径对应原图的一个割即可

最后答案就是最短路

  1 type node=record
  2        loc,num:longint;
  3      end;
  4      cmp=record
  5        point,next,cost:longint;
  6      end;
  7 
  8 var edge:array[0..1100000] of cmp;
  9     heap:array[0..300010] of node;
 10     p,d,where:array[0..300010] of longint;
 11     t,m,n,i,j,k,x,y,len:longint;
 12 
 13 procedure swap(var a,b:node);
 14   var c:node;
 15   begin
 16     c:=a;
 17     a:=b;
 18     b:=c;
 19   end;
 20 
 21 procedure add(x,y,z:longint);
 22   begin
 23     inc(len);
 24     edge[len].point:=y;
 25     edge[len].cost:=z;
 26     edge[len].next:=p[x];
 27     p[x]:=len;
 28   end;
 29 
 30 procedure up(i:longint);
 31   var j,x,y:longint;
 32   begin
 33     j:=i shr 1;
 34     while j>0 do
 35     begin
 36       if heap[i].num<heap[j].num then
 37       begin
 38         x:=heap[i].loc;
 39         y:=heap[j].loc;
 40         where[x]:=j;
 41         where[y]:=i;
 42         swap(heap[i],heap[j]);
 43         i:=j;
 44         j:=i shr 1;
 45       end
 46       else break;
 47     end;
 48   end;
 49 
 50 procedure sift(i:longint);
 51   var j,x,y:longint;
 52   begin
 53     j:=i shl 1;
 54     while j<=m do
 55     begin
 56       if (j<m) and (heap[j].num>heap[j+1].num) then inc(j);
 57       if heap[i].num>heap[j].num then
 58       begin
 59         x:=heap[i].loc;
 60         y:=heap[j].loc;
 61         where[x]:=j;
 62         where[y]:=i;
 63         swap(heap[i],heap[j]);
 64         i:=j;
 65         j:=i shl 1;
 66       end
 67       else break;
 68     end;
 69   end;
 70 
 71 begin
 72   readln(n);
 73   fillchar(p,sizeof(p),255);
 74   t:=n*n+2;
 75   for i:=1 to n do
 76   begin
 77     readln(x);
 78     add(1,i+1,x);
 79   end;
 80   for i:=1 to n do
 81     for j:=1 to n do
 82     begin
 83       readln(x);
 84       if i=n then y:=t
 85       else y:=i*n+j+1;
 86       add((i-1)*n+j+1,y,x);
 87     end;
 88 
 89   for i:=1 to n do
 90   begin
 91     readln(x);
 92     add((i-1)*n+2,t,x);
 93     for j:=2 to n do
 94     begin
 95       readln(x);
 96       add((i-1)*n+j+1,(i-1)*n+j,x);
 97     end;
 98     readln(x);
 99     add(1,i*n+1,x);
100   end;
101 
102   for i:=1 to n do
103   begin
104     readln(x);
105     add(i+1,1,x);
106   end;
107   for i:=1 to n do
108     for j:=1 to n do
109     begin
110       readln(x);
111       if i=n then y:=t
112       else y:=i*n+j+1;
113       add(y,(i-1)*n+j+1,x);
114     end;
115 
116   for i:=1 to n do
117   begin
118     readln(x);
119     add(t,(i-1)*n+2,x);
120     for j:=2 to n do
121     begin
122       readln(x);
123       add((i-1)*n+j,(i-1)*n+j+1,x);
124     end;
125     readln(x);
126     add(i*n+1,1,x);
127   end;
128   m:=t;
129   for i:=1 to t do
130   begin
131     if i=1 then d[i]:=0
132     else d[i]:=10000007;
133     heap[i].loc:=i;
134     heap[i].num:=d[i];
135     where[i]:=i;
136   end;
137   for i:=1 to t do
138   begin
139     k:=heap[1].loc;
140     if k=t then break;
141     x:=heap[m].loc;
142     where[x]:=1;
143     swap(heap[1],heap[m]);
144     dec(m);
145     sift(1);
146     j:=p[k];
147     while j<>-1 do
148     begin
149       y:=edge[j].point;
150       if d[y]>edge[j].cost+d[k] then
151       begin
152         d[y]:=edge[j].cost+d[k];
153         heap[where[y]].num:=d[y];
154         up(where[y]);
155       end;
156       j:=edge[j].next;
157     end;
158   end;
159   writeln(d[t]);
160 end.
View Code

 

posted on 2014-09-05 22:12  acphile  阅读(158)  评论(0编辑  收藏  举报