语文挂科了,所以来除草了。
program p2007;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | type d=record w,po:int64; end; bian=record next,point,w:int64; end; var b:array[1..1000000] of bian; i,j,n,k1,k2,len:longint; x:array[1..1000000] of d; p,f:array[0..1000000] of int64; pd:array[0..1000000] of boolean; maxn:int64; procedure add(k1,k2,k3:longint); begin inc(len); b[len].next:=p[k1]; b[len].point:=k2; b[len].w:=k3; p[k1]:=len; end; function mi(k1,k2:longint):longint; begin if x[k1].w>x[k2].w then exit (k2) else exit (k1); end; function min(k1,k2,k3:longint):longint; begin exit (mi(mi(k1,k2),k3)); end; procedure press(k:longint); var k1:longint; k2:d; begin k1:=min(k,k*2,k*2+1); if k1=k then exit ; k2:=x[k1]; x[k1]:=x[k]; x[k]:=k2; press(k1); end; procedure find(k:longint); var k1:d; begin if k=1 then exit ; if x[k div 2].w>x[k].w then begin k1:=x[k]; x[k]:=x[k div 2]; x[k div 2]:=k1; find(k div 2); end; end; function dijstra:longint; var k1,k2,k3,i,j,now,len:longint; k:d; begin fillchar(pd, sizeof (pd), true ); fillchar(x, sizeof (x),$7f); maxn:=x[1].po; len:=1; fillchar(f, sizeof (f),$3f); x[1].po:=0; x[1].w:=0; f[0]:=0; while len>0 do begin len:=len-1; k:=x[1]; if len>0 then begin x[1]:=x[len+1]; x[len+1].w:=maxn; press(1); end; if pd[k.po]= false then continue ; pd[k.po]:= false ; k2:=p[k.po]; while k2>0 do begin k1:=b[k2].point; if f[k.po]+b[k2].w<f[k1] then begin f[k1]:=f[k.po]+b[k2].w; inc(len); x[len].po:=k1; x[len].w:=f[k1]; find(len); end; k2:=b[k2].next; end; end; exit (f[n*n+1]); end; begin fillchar(b, sizeof (b),0); fillchar(p, sizeof (p),0); len:=0; readln(n); for i:=1 to n+1 do for j:=1 to n do begin readln(k1); if i=1 then add(j,n*n+1,k1) else if i=n+1 then add(0,n*(n-1)+j,k1) else add(n*(i-1)+j,n*(i-2)+j,k1); end; for i:=1 to n do begin readln(k1); add(0,n*i-n+1,k1); for j:=1 to n-1 do begin readln(k1); add(n*i-n+j,n*i-n+j+1,k1); end; readln(k1); add(n*i,n*n+1,k1); end; for i:=1 to n+1 do for j:=1 to n do begin readln(k1); if (i<>1) and (i<>n+1) then add(n*(i-2)+j,n*(i-1)+j,k1); end; for i:=1 to n do begin readln(k1); for j:=1 to n-1 do begin readln(k1); add(n*i-n+j+1,n*i-n+j,k1); end; readln(k1); end; fillchar(x, sizeof (x),$3f); fillchar(f, sizeof (f),$3f); maxn:=x[1].po; writeln(dijstra); end. |
一眼就可以看出来是最小割,因为显而易见每个点的高度只可能是0或1,那么它们必有一个交接面,而这个就需要用最小割了。但是最小割会T80,所以要用对偶图+最短路来解决最小割问题,就如BZOJ1001。而这题恶心的把SPFA卡了,我又都比的把DJ+堆敲炸了,这道题就坑了我一个晚上QAQ(虽然有OSU和CS的因素)。