狼抓兔子(平面图转对偶图求最短路)
一个网格图中求最小割,很特殊的是这个图是一个平面图,最小割=最大流=对偶图中最短路,把小三角换成点标号,重连边即可。
我标号用的矩阵元素标号的思想,可能看着还算清楚,乘来乘去的。
数据里还有n == 1和m == 1的数据。。。。。
插个图片帮助理解。
View Code
1 program beijing2006(input,output); 2 const 3 oo = 999999999; 4 type 5 node = ^link; 6 link = record 7 goal,w : longint; 8 next : node; 9 end; 10 var 11 l : array[0..2500000] of node; 12 d : array[0..2500000] of int64; 13 v : array[0..2500000] of boolean; 14 q : array[0..2500000] of longint; 15 n,m,sum : longint; 16 start,final : longint; 17 procedure add(xx,yy,ww: longint ); 18 var 19 tt : node; 20 begin 21 new(tt); 22 tt^.goal:=yy; 23 tt^.w:=ww; 24 tt^.next:=l[xx]; 25 l[xx]:=tt; 26 end; { add } 27 function check():boolean; 28 var 29 i,x : longint; 30 answer : int64; 31 begin 32 answer:=oo; 33 if n=1 then 34 begin 35 for i:=1 to m-1 do 36 begin 37 read(x); 38 if x<answer then 39 answer:=x; 40 end; 41 writeln(answer); 42 exit(true); 43 end; 44 if m=1 then 45 begin 46 for i:=1 to n-1 do 47 begin 48 read(x); 49 if x<answer then 50 answer:=x; 51 end; 52 writeln(answer); 53 exit(true); 54 end; 55 exit(false); 56 end; { check } 57 procedure init; 58 var 59 i : longint; 60 begin 61 readln(n,m); 62 for i:=0 to 2*m*n+3 do 63 l[i]:=nil; 64 sum:=(n-1)*(m-1); 65 Start:=0; 66 final:=(m-1)+(m-1)*2*(n-1)+1; 67 end; { init } 68 procedure make_graph; 69 var 70 i,j : longint; 71 ww : longint; 72 begin 73 for i:=1 to n do 74 for j:=1 to m-1 do 75 begin 76 read(ww); 77 if i=1 then 78 begin 79 add(final,(i*(m-1)+j)+sum,ww); 80 add((i*(m-1)+j)+sum,final,ww); 81 end 82 else 83 if i=n then 84 begin 85 add((i-1)*(m-1)+j,start,ww); 86 add(start,(i-1)*(m-1)+j,ww); 87 end 88 else 89 begin 90 add((i-1)*(m-1)+j,i*(m-1)+j+sum,ww); 91 add(i*(m-1)+j+sum,(i-1)*(m-1)+j,ww); 92 end; 93 end; 94 for i:=1 to n-1 do 95 for j:=1 to m do 96 begin 97 read(ww); 98 if j=1 then 99 begin 100 add(start,i*(m-1)+j,ww); 101 add(i*(m-1)+j,start,ww); 102 end 103 else 104 if j=m then 105 begin 106 add(final,i*(m-1)+j-1+sum,ww); 107 add(i*(m-1)+j-1+sum,final,ww); 108 end 109 else 110 begin 111 add(i*(m-1)+j,i*(m-1)+j-1+sum,ww); 112 add(i*(m-1)+j-1+sum,i*(m-1)+j,ww); 113 end; 114 end; 115 for i:=1 to n-1 do 116 for j:=1 to m-1 do 117 begin 118 read(ww); 119 add(i*(m-1)+j,i*(m-1)+j+sum,ww); 120 add(i*(m-1)+j+sum,i*(m-1)+j,ww); 121 end; 122 end; { make_graph } 123 procedure spfa(); 124 var 125 head,tail : longint; 126 t : node; 127 begin 128 fillchar(v,sizeof(v),false); 129 fillchar(d,sizeof(d),63); 130 head:=0; 131 tail:=1; 132 v[start]:=true; 133 q[1]:=start; 134 d[start]:=0; 135 while head<>tail do 136 begin 137 inc(head); 138 if head=2500000 then 139 head:=0; 140 v[q[head]]:=false; 141 t:=l[q[head]]; 142 while t<>nil do 143 begin 144 if d[q[head]]+t^.w<d[t^.goal] then 145 begin 146 d[t^.goal]:=d[q[head]]+t^.w; 147 if not v[t^.goal] then 148 begin 149 inc(tail); 150 if tail=2500000 then 151 tail:=0; 152 q[tail]:=t^.goal; 153 v[t^.goal]:=true; 154 end; 155 end; 156 t:=t^.next; 157 end; 158 end; 159 end; { spfa } 160 procedure print; 161 begin 162 writeln(d[final]); 163 end; { print } 164 begin 165 init; 166 if not check() then 167 begin 168 make_graph(); 169 spfa(); 170 print; 171 end; 172 end.