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