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.
posted @ 2019-01-25 21:45  _ARFA  阅读(114)  评论(0编辑  收藏  举报