题目
“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......”
Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干!
Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。
通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。
Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
【数据范围】
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
题意
给你一个n*m的矩阵,让你求用尽量少的篱笆,把羊和狼分开。
分析
我们可以发现,这题的篱笆,就是把两个集合(羊和狼)一分为二,而且又是费用最小,所以我们自然的想到了最小割。
我们接着考虑建图:
从源点向所有的狼连一条容量为maxlongint的边,然后再从所有的羊向汇点连一条容量为maxlongint的边,狼向周围的空地和羊连容量为1的边,空地往周围空地和羊连一条容量为1的边,这样跑一次最大流便可以了。
代码
var
n,m,i,j,nu,x,y,t,s,k,ans:longint;
bd:array[1..4,1..2] of longint=((0,1),(1,0),(-1,0),(0,-1));
b,las,nex,f,re,d,dis:array[0..200000] of longint;
a:array[1..100,1..100] of longint;
procedure insert(x,y,z:longint);
begin
inc(nu);b[nu]:=y;nex[nu]:=las[x];las[x]:=nu;f[nu]:=z;re[nu]:=nu+1;
inc(nu);b[nu]:=x;nex[nu]:=las[y];las[y]:=nu;f[nu]:=0;re[nu]:=nu-1;
end;
function bfs:boolean;
var l,r,p:longint;
begin
l:=0;r:=1;fillchar(dis,sizeof(dis),0);dis[0]:=1;d[1]:=0;
while l<r do begin
inc(l);p:=las[d[l]];
while p<>0 do begin
if (dis[b[p]]=0)and(f[p]>0) then begin
dis[b[p]]:=dis[d[l]]+1;inc(r);d[r]:=b[p];
end;p:=nex[p];
end;
end;
exit(dis[t]<>0);
end;
function min(l,r:longint):longint;
begin
if l<r then exit(l);exit(r);
end;
function dinic(x,y:longint):longint;
var p,o:longint;
begin
if x=t then exit(y);
p:=las[x];dinic:=0;
while p<>0 do begin
if (f[p]>0)and(dis[b[p]]=dis[x]+1) then begin
o:=dinic(b[p],min(y,f[p]));
if o<>0 then begin
dec(f[p],o);inc(f[re[p]],o);
dec(y,o);inc(dinic,o);if y=0 then break;
end;
end;p:=nex[p];
end;
end;
begin
readln(n,m);
for i:=1 to n do begin
for j:=1 to m do read(a[i,j]);
readln;
end;
for i:=1 to n do
for j:=1 to m do begin
if a[i,j]=1 then insert(0,(i-1)*m+j,maxlongint)
else if a[i,j]=2 then insert((i-1)*m+j,n*m+1,maxlongint);
if a[i,j]<>2 then
for k:=1 to 4 do begin
x:=i+bd[k,1];y:=j+bd[k,2];
if (x<1)or(y<1)or(x>n)or(y>m) then continue;
if a[x,y]<>1 then insert((i-1)*m+j,(x-1)*m+y,1);
end;
end;
t:=n*m+1;
while bfs do ans:=ans+dinic(0,maxlongint);
writeln(ans);
end.