## bzoj 1412 最小割 网络流

比较明显的最小割建模， 因为我们需要把狼和羊分开。

那么我们连接source和每个羊，流量为inf，代表这条边不能成为最小割中的点，同理连接每个狼和汇，流量为inf，正确性同上，那么对于每个相邻的羊和狼，连接边，流量为1，代表隔开这两个点需要1的代价，对于每个空地和狼或者羊，连接边，流量为1，代表隔开这个两个点的代价为1，同时需要注意的是，对于空地之间的连边也应该是1，因为很有可能狼和羊通过空地相遇。这样做最大流就行了。

反思：手残将空地之间的连成inf了。。。

/**************************************************************
Problem: 1412
Language: Pascal
Result: Accepted
Time:112 ms
Memory:3152 kb
****************************************************************/

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;
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.

posted on 2014-01-17 12:49  BLADEVIL  阅读(374)  评论(0编辑  收藏  举报