P2598 [ZJOI2009]狼和羊的故事
当一个羊身边有狼时产生贡献,最多只有四周。
-
所有源点连狼,代表这些狼可以产生贡献。
-
所有地连四周,代表狼可以对一定地理位置的羊产生贡献。
-
所有羊连汇点,代表回收贡献。
// luogu-judger-enable-o2
Uses math;
var
value,reach,next,from:array[-1..210000] of longint;
id,matrix:array[-1..101,-1..101] of longint;
gap,dis,cnt:array[-1..810000] of longint;
n,m,l,r,k,i,j,num,tot,sink,source,maxflow:longint;
procedure add(l,r,sum:longint);
begin
inc(tot); from[tot]:=l; reach[tot]:=r; value[tot]:=sum; next[tot]:=cnt[l]; cnt[l]:=tot;
inc(tot); from[tot]:=r; reach[tot]:=l; value[tot]:=8-8; next[tot]:=cnt[r]; cnt[r]:=tot;
end;
function Dfs(now,flow:longint):longint;
var i,k,mindis,ret:longint;
begin
mindis:=n-1; ret:=flow;
if now=sink then exit(flow);
i:=cnt[now];
while i<>-1 do
begin
if value[i]>0 then
begin
if dis[now]=dis[reach[i]]+1 then
begin
k:=Dfs(reach[i],min(ret,value[i]));
dec(value[i],k);inc(value[i xor 1],k);
dec(ret,k);
if dis[source]>=n then exit(flow-ret);
if ret=0 then break;
end;
mindis:=min(mindis,dis[reach[i]]);
end;
i:=next[i];
end;
if ret=flow then
begin
dec(gap[dis[now]]);
if gap[dis[now]]=0 then dis[source]:=n;
dis[now]:=mindis+1;
inc(gap[dis[now]]);
end;
exit(flow-ret);
end;
begin
filldword(cnt,sizeof(cnt) div 4,maxlongint*2+1); tot:=1;
read(n,m); source:=1; sink:=n*m+2; num:=1;
for i:=1 to n do for j:=1 to m do
begin
inc(num); id[i,j]:=num;
read(matrix[i,j]);
end;
for i:=1 to n do for j:=1 to m do
begin
if matrix[i,j]=1 then add(id[i,j],sink,maxlongint div 843);
if matrix[i,j]=2 then add(source,id[i,j],maxlongint div 843);
if (i-1>0) then add(id[i,j],id[i-1,j],1);
if (i+1<=n) then add(id[i,j],id[i+1,j],1);
if (j-1>0) then add(id[i,j],id[i,j-1],1);
if (j+1<=m) then add(id[i,j],id[i,j+1],1);
end;
n:=sink+1; gap[source]:=n;
while dis[source]<n do inc(maxflow,Dfs(source,maxlongint));
writeln(maxflow);
end.
完结撒花!✿✿ヽ(゚▽゚)ノ✿