【BZOJ1412】狼和羊的故事(最小割)
题意:将一个由0,1,2构成的矩阵里的1与2全部分割最少需要选取多少条边
n,m<=100
思路:裸的最小割模型
相邻的格子连容量为1的边(其实可以少连很多遍,1与1,2与2之间的边是没有意义的)
由源点到所有1连容量为oo的边,2到汇点连容量为oo的边
最小割即是答案
1 const dx:array[1..4]of longint=(-1,0,0,1); 2 dy:array[1..4]of longint=(0,-1,1,0); 3 var head,vet,next,len,dis,gap,fan:array[0..200000]of longint; 4 num,a:array[1..300,1..300]of longint; 5 n,m,i,j,x,y,tot,s,source,src,k:longint; 6 7 procedure add(a,b,c:longint); 8 begin 9 inc(tot); 10 next[tot]:=head[a]; 11 vet[tot]:=b; 12 len[tot]:=c; 13 head[a]:=tot; 14 end; 15 16 function min(x,y:longint):longint; 17 begin 18 if x<y then exit(x); 19 exit(y); 20 end; 21 22 function dfs(u,aug:longint):longint; 23 var e,v,val,t,flow:longint; 24 begin 25 if u=src then exit(aug); 26 e:=head[u]; val:=s-1; flow:=0; 27 while e<>0 do 28 begin 29 v:=vet[e]; 30 if len[e]>0 then 31 begin 32 if dis[u]=dis[v]+1 then 33 begin 34 t:=dfs(v,min(aug-flow,len[e])); 35 len[e]:=len[e]-t; 36 len[fan[e]]:=len[fan[e]]+t; 37 flow:=flow+t; 38 if dis[source]>=s then exit(flow); 39 if aug=flow then break; 40 end; 41 val:=min(val,dis[v]); 42 end; 43 e:=next[e]; 44 end; 45 if flow=0 then 46 begin 47 dec(gap[dis[u]]); 48 if gap[dis[u]]=0 then dis[source]:=s; 49 dis[u]:=val+1; 50 inc(gap[dis[u]]); 51 end; 52 exit(flow); 53 end; 54 55 function maxflow:longint; 56 var ans:longint; 57 begin 58 fillchar(gap,sizeof(gap),0); 59 fillchar(dis,sizeof(dis),0); 60 gap[0]:=s; ans:=0; 61 while dis[source]<s do ans:=ans+dfs(source,maxlongint); 62 exit(ans); 63 end; 64 65 begin 66 assign(input,'bzoj1412.in'); reset(input); 67 assign(output,'bzoj1412.out'); rewrite(output); 68 readln(n,m); 69 for i:=1 to n do 70 for j:=1 to m do 71 begin 72 read(a[i,j]); 73 inc(s); num[i,j]:=s; 74 end; 75 for i:=1 to 200000 do 76 if i mod 2=1 then fan[i]:=i+1 77 else fan[i]:=i-1; 78 for i:=1 to n do 79 for j:=1 to m do 80 for k:=1 to 4 do 81 begin 82 x:=i+dx[k]; y:=j+dy[k]; 83 if (x>0)and(x<=n)and(y>0)and(y<=m) then 84 begin 85 add(num[i,j],num[x,y],1); 86 add(num[x,y],num[i,j],0); 87 end; 88 end; 89 source:=s+1; src:=s+2; s:=s+2; 90 for i:=1 to n do 91 for j:=1 to m do 92 begin 93 if a[i,j]=1 then 94 begin 95 add(source,num[i,j],maxlongint); 96 add(num[i,j],source,0); 97 end; 98 if a[i,j]=2 then 99 begin 100 add(num[i,j],src,maxlongint); 101 add(src,num[i,j],0); 102 end; 103 end; 104 105 writeln(maxflow); 106 close(input); 107 close(output); 108 end.
null