bzoj1001: [BeiJing2006]狼抓兔子
题目链接http://www.lydsy.com:808/JudgeOnline/problem.php?id=1001
可以很显然地看出来这道题是一个裸的最大流,但是边数是10^6级别的,不T才怪。
平面图上最大流等于他的最小割,这是挺显然的吧,因为斜着这么插过去肯定要经过所有的流量。
所以我们求它的对偶图,以左下为s,右上为t,求一次最短路径就是最小割了。
用dijkstra+heap实现,这时候c++的巨大优势就体现出来了
(其实是我当时太弱了不会spfa)(注意m=1或n=1的时候要特判,因为它wa好几次)
代码:
1 program xx; 2 uses math; 3 4 type xxx=record 5 key,pos:longint; 6 end; 7 8 var heng,shu,xie:array[0..1110,0..1110] of longint; 9 i,j,k,n,m,p,q,r,en,tot,node,ans:longint; 10 dis,inh:array[0..2500010] of longint; 11 heap:array[0..2500010] of xxx; 12 ed,len:array[0..2500010,1..3] of longint; 13 vis:array[0..2500010] of boolean; 14 15 procedure swap(var a,b:xxx); 16 var t:xxx; 17 begin 18 t:=a; 19 a:=b; 20 b:=t; 21 end; 22 23 procedure swapn(var a,b:longint); 24 var t:longint; 25 begin 26 t:=a; 27 a:=b; 28 b:=t; 29 end; 30 31 procedure link2(x:longint); 32 begin 33 if i mod j=0 34 then 35 begin 36 ed[x,1]:=en; 37 len[x,1]:=shu[(i-1) div j+1,m]; 38 end 39 else 40 begin 41 ed[x,1]:=x+1; 42 len[x,1]:=shu[(i-1) div j+1,(i-1) mod j shr 1+2]; 43 end; 44 if i>j then 45 begin 46 ed[x,2]:=x-j-1; 47 len[x,2]:=heng[(i-1) div j+1,(i-1) mod j shr 1+1]; 48 end 49 else begin 50 ed[x,2]:=en; 51 len[x,2]:=heng[1,i shr 1]; 52 end; 53 ed[x,3]:=x-1; 54 len[x,3]:=xie[(i-1) div j+1,(i-1) mod j shr 1+1]; 55 end; 56 57 procedure link1(x:longint); 58 begin 59 if i mod j<>1 then 60 begin 61 ed[x,1]:=x-1; 62 len[x,1]:=shu[(i-1) div j+1,(i-1) mod j shr 1+1]; 63 end; 64 if i<en-j then 65 begin 66 ed[x,2]:=x+j+1; 67 len[x,2]:=heng[(i-1) div j+2,(i-1) mod j shr 1+1]; 68 end; 69 ed[x,3]:=x+1; 70 len[x,3]:=xie[(i-1) div j+1,(i-1) mod j shr 1+1]; 71 end; 72 73 procedure insert(x,y,node:longint); 74 begin 75 heap[x].key:=y; 76 heap[x].pos:=node; 77 inh[node]:=x; 78 while (x<>1) and (heap[x].key<heap[x shr 1].key) do 79 begin 80 swapn(inh[heap[x].pos],inh[heap[x shr 1].pos]); 81 swap(heap[x],heap[x shr 1]); 82 x:=x shr 1; 83 end; 84 end; 85 86 procedure delete(x:longint); 87 var k:longint; 88 begin 89 swapn(inh[heap[x].pos],inh[heap[tot].pos]); 90 swap(heap[x],heap[tot]); 91 heap[tot].key:=maxlongint; 92 inh[heap[tot].pos]:=0; 93 heap[tot].pos:=0; 94 while x shl 1<=tot-1 do 95 begin 96 if heap[x shl 1].key<heap[x shl 1+1].key 97 then k:=x shl 1 98 else k:=x shl 1+1; 99 if heap[x].key>heap[k].key 100 then 101 begin 102 swapn(inh[heap[x].pos],inh[heap[k].pos]); 103 swap(heap[x],heap[k]); 104 x:=k; 105 end 106 else break 107 end; 108 end; 109 110 begin 111 readln(n,m); 112 ans:=maxlongint; 113 for i:=1 to n do 114 for j:=1 to m-1 do 115 begin 116 read(heng[i,j]); 117 ans:=min(ans,heng[i,j]); 118 end; 119 for i:=1 to n-1 do 120 for j:=1 to m do 121 begin 122 read(shu[i,j]); 123 ans:=min(ans,shu[i,j]); 124 end; 125 for i:=1 to n-1 do 126 for j:=1 to m-1 do 127 begin 128 read(xie[i,j]); 129 ans:=min(xie[i,j],ans); 130 end; 131 if (n=1) or (m=1) then 132 begin 133 writeln(ans); 134 exit; 135 end; 136 en:=(n-1)*(m-1) shl 1+1; 137 j:=2*(m-1); 138 heap[en].key:=maxlongint; 139 dis[en]:=maxlongint; 140 for i:=1 to (n-1)*(m-1)*2 do 141 begin 142 dis[i]:=maxlongint; 143 heap[i].key:=maxlongint; 144 if i mod (2*(m-1))=1 then dis[i]:=min(dis[i],shu[(i-1) div j+1,1]); 145 if (i mod 2=1) and ((i-1) div j+2>=n) 146 then dis[i]:=min(dis[i],heng[n,(i-1) mod j shr 1+1]); 147 if dis[i]<>maxlongint then 148 begin 149 inc(tot); 150 insert(tot,dis[i],i); 151 end; 152 if i mod 2=0 153 then link2(i) 154 else link1(i); 155 end; 156 while tot>0 do 157 begin 158 node:=heap[1].pos; 159 if node=en then 160 begin 161 writeln(dis[en]); 162 exit; 163 end; 164 if not(vis[node]) then 165 for i:=1 to 3 do 166 if ed[node,i]<>0 then 167 begin 168 k:=ed[node,i]; 169 if dis[node]+len[node,i]<dis[k] then 170 begin 171 dis[k]:=dis[node]+len[node,i]; 172 if inh[k]=0 173 then 174 begin 175 inc(tot); 176 insert(tot,dis[k],k); 177 end 178 else insert(inh[k],dis[k],k); 179 end; 180 end; 181 delete(1); 182 dec(tot); 183 vis[node]:=true; 184 end; 185 writeln(dis[en]); 186 end.