Description
“狼爱上羊啊爱的疯狂,谁让他们真爱了一场;狼爱上羊啊并不荒唐,他们说有爱就有方向......”
Orez听到这首歌,心想:狼和羊如此和谐,为什么不尝试羊狼合养呢?说干就干!
Orez的羊狼圈可以看作一个n*m个矩阵格子,这个矩阵的边缘已经装上了篱笆。可是Drake很快发现狼再怎么也是狼,它们总是对羊垂涎三尺,那首歌只不过是一个动人的传说而已。所以Orez决定在羊狼圈中再加入一些篱笆,还是要将羊狼分开来养。
通过仔细观察,Orez发现狼和羊都有属于自己领地,若狼和羊们不能呆在自己的领地,那它们就会变得非常暴躁,不利于他们的成长。
Orez想要添加篱笆的尽可能的短。当然这个篱笆首先得保证不能改变狼羊的所属领地,再就是篱笆必须修筑完整,也就是说必须修建在单位格子的边界上并且不能只修建一部分。
Input
输入数据存放在文本文件ws.in中。
文件的第一行包含两个整数n和m。接下来n行每行m个整数,1表示该格子属于狼的领地,2表示属于羊的领地,0表示该格子不是任何一只动物的领地。
Output
输出数据存放在文本文件ws.out中。
文件中仅包含一个整数ans,代表篱笆的最短长度。
Sample Input
2 2
2 2
1 1
Sample Output
2
Data Constraint
Hint
【数据范围】
10%的数据 n,m≤3
30%的数据 n,m≤20
100%的数据 n,m≤100
分析:一道水题。每一个单位的栅栏就是把两个相邻的点分开,显然想到最小割。源点到每只羊连一条INF的边,每只狼到汇点连一条INF的边,每只羊想周围空地及狼连一条1的边,空地向其他空地及狼连一条1的边,然后最大流。
代码:
const
maxv=100000;
dx:array [1..4] of longint=(1,0,-1,0);
dy:array [1..4] of longint=(0,1,0,-1);
type
node=record
y,c,op,next:longint;
end;
var
g:array [1..maxv] of node;
a:array [1..101,1..101] of longint;
ls,dis,cur:Array [0..maxv] of longint;
list:array [0..maxv] of longint;
n,m,e,s,t,ans:longint;
function po(x,y:longint):longint;
begin
exit((x-1)*m+y);
end;
function check(x,y:longint):boolean;
begin
if (x>0) and (y>0) and (x<=n) and (y<=m) then exit(true)
else exit(false);
end;
procedure add(u,v,c:longint);
begin
inc(e);
g[e].y:=v; g[e].c:=c; g[e].op:=e+1; g[e].next:=ls[u]; ls[u]:=e;
inc(e);
g[e].y:=u; g[e].c:=0; g[e].op:=e-1; g[e].next:=ls[v]; ls[v]:=e;
end;
procedure init;
var i,j,k:longint;
begin
readln(n,m);
for i:=1 to n do
for j:=1 to m do
read(a[i,j]);
for i:=1 to n do
for j:=1 to m do
begin
if a[i,j]=1 then
begin
add(0,po(i,j),maxlongint);
for k:=1 to 4 do
if check(i+dx[k],j+dy[k]) then
if a[i+dx[k],j+dy[k]]<>1 then
add(po(i,j),po(i+dx[k],j+dy[k]),1);
end;
if a[i,j]=2 then add(po(i,j),n*m+1,maxlongint);
if a[i,j]=0 then
begin
for k:=1 to 4 do
if check(i+dx[k],j+dy[k]) then
if a[i+dx[k],j+dy[k]]<>1 then
add(po(i,j),po(i+dx[k],j+dy[k]),1);
end;
end;
end;
function bfs:boolean;
var
i,head,tail,u:longint;
begin
for i:=s to t do
dis[i]:=0;
dis[s]:=1;
head:=0; tail:=1;
list[tail]:=s;
repeat
head:=(head+1) mod maxv;
u:=list[head];
i:=ls[u];
while i>0 do
begin
if (g[i].c<>0) and (dis[g[i].y]=0) then
begin
dis[g[i].y]:=dis[u]+1;
if g[i].y=t then exit(true);
tail:=(tail+1) mod maxv;
list[tail]:=g[i].y;
end;
i:=g[i].next;
end;
until head=tail;
exit(false);
end;
function min(x,y:longint):longint;
begin
if x<y then exit(x)
else exit(y);
end;
function dfs(x,maxf:longint):longint;
var ret,i,f:longint;
begin
if (x=t) or (maxf=0) then exit(maxf);
ret:=0;
i:=ls[x];
while i>0 do
begin
if (g[i].c<>0) and (dis[g[i].y]=dis[x]+1) then
begin
f:=dfs(g[i].y,min(maxf,g[i].c));
dec(g[i].c,f);
inc(g[g[i].op].c,f);
ret:=ret+f;
end;
if ret=maxf then break;
i:=g[i].next;
end;
exit(ret);
end;
procedure dinic;
var i:longint;
begin
while bfs do
begin
for i:=s to t do
cur[i]:=ls[i];
ans:=ans+dfs(s,maxlongint);
end;
end;
begin
init;
s:=0; t:=n*m+1;
dinic;
writeln(ans);
end.