首先不难发现海拔高度只能为0或1
因为决策是单调的
不难发现最优决策一定是划分为海拔为0和1两块,不会出现01相间的情况
所以这很明显是一个最小割
由于n*n很大,我们必须要用平面图最小割转化为最短路径
在我们做1001时,是平面无向图,这里是平面有向图,其实是一样的
只要记住以起点终点为对角线划分外面为两个面,然后以面为点,边两侧面连边
最后注意新图的任意一条路径对应原图的一个割即可
最后答案就是最短路
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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.