bzoj 1412 最小割 网络流
比较明显的最小割建模, 因为我们需要把狼和羊分开。
那么我们连接source和每个羊,流量为inf,代表这条边不能成为最小割中的点,同理连接每个狼和汇,流量为inf,正确性同上,那么对于每个相邻的羊和狼,连接边,流量为1,代表隔开这两个点需要1的代价,对于每个空地和狼或者羊,连接边,流量为1,代表隔开这个两个点的代价为1,同时需要注意的是,对于空地之间的连边也应该是1,因为很有可能狼和羊通过空地相遇。这样做最大流就行了。
反思:手残将空地之间的连成inf了。。。
/************************************************************** Problem: 1412 User: BLADEVIL Language: Pascal Result: Accepted Time:112 ms Memory:3152 kb ****************************************************************/ //By BLADEVIL var n, m :longint; num, map :array[0..210,0..210] of longint; pre, other, len :array[0..200010] of longint; last :array[0..20010] of longint; l :longint; source, sink :longint; go :array[0..2,0..4] of longint; que, d :array[0..20010] of longint; ans :longint; procedure connect(x,y,z:longint); begin inc(l); pre[l]:=last[x]; last[x]:=l; other[l]:=y; len[l]:=z; end; function min(a,b:longint):longint; begin if a>b then exit(b) else exit(a); end; procedure init; var i, j, k :longint; x :longint; nx, ny :longint; begin go[1,1]:=-1; go[2,2]:=1; go[1,3]:=1; go[2,4]:=-1; read(n,m); l:=1; for i:=1 to n do for j:=1 to m do num[i,j]:=(i-1)*m+j; source:=n*m+2; sink:=source+1; for i:=1 to n do for j:=1 to m do read(map[i,j]); for i:=1 to n do for j:=1 to m do begin if map[i,j]=1 then begin connect(source,num[i,j],maxlongint); connect(num[i,j],source,0); end else if map[i,j]=2 then begin connect(num[i,j],sink,maxlongint); connect(sink,num[i,j],0); end; for k:=1 to 4 do begin nx:=i+go[1,k]; ny:=j+go[2,k]; if (nx<1) or (nx>n) or (ny<1) or (ny>m) then continue; if map[i,j]<>map[nx,ny] then begin connect(num[i,j],num[nx,ny],1); connect(num[nx,ny],num[i,j],0); end; if (map[i,j]=map[nx,ny]) and (map[i,j]=0) then begin connect(num[i,j],num[nx,ny],1); connect(num[nx,ny],num[i,j],0); end; end; end; end; function bfs:boolean; var q, p :longint; h, t, cur :longint; begin fillchar(d,sizeof(d),0); que[1]:=source; d[source]:=1; h:=0; t:=1; while h<t do begin inc(h); cur:=que[h]; q:=last[cur]; while q<>0 do begin p:=other[q]; if (len[q]>0) and (d[p]=0) then begin inc(t); que[t]:=p; d[p]:=d[cur]+1; if p=sink then exit(true); end; q:=pre[q]; end; end; exit(false); end; function dinic(x,flow:longint):longint; var q, p :longint; tmp, rest :longint; begin if x=sink then exit(flow); rest:=flow; q:=last[x]; while q<>0 do begin p:=other[q]; if (len[q]>0) and (d[p]=d[x]+1) and (rest>0) then begin tmp:=dinic(p,min(rest,len[q])); dec(rest,tmp); dec(len[q],tmp); inc(len[q xor 1],tmp); end; q:=pre[q]; end; exit(flow-rest); end; procedure main; begin while bfs do ans:=ans+dinic(source,maxlongint); writeln(ans); end; begin init; main; end.