您的位置:首页 > 理论基础 > 计算机网络

bzoj 1066 最大流

2017-01-27 22:03 302 查看
题意:r行c列的网络中有一些高低不同的石柱,每行每列相邻石柱距离为1,一些石柱上有蜥蜴,每个蜥蜴可以跳到平面距离不超过d的任意石柱上。每次蜥蜴跳跃时离开的石柱高度减一,到达的石柱高度不变。当石柱高度为0时其他蜥蜴不能落脚。任意时刻同一个石柱上不能有超过一只的蜥蜴。让尽量多的蜥蜴逃到边界外,输出无法逃离的蜥蜴。即输出无法蜥蜴的最小值。

最大流

建图:源点连每个有蜥蜴的柱子,流量为1每个能跳到边界外的柱子(初始高度大于0的)连汇点,流量为正无穷;由于每个柱子有能走蜥蜴的限制,把每个柱子(初始高度大于0的)拆成出入两个点,每个柱子的出入两个点之间流量为石柱高度(能走蜥蜴的总数),每个出点连能到达的柱子的入点,流量为正无穷

var
n,m,d,l,ss,st :longint;
s :string;
ans,sum,x :longint;
i,j,ii,jj :longint;
last :array[0..1010] of longint;
dis :array[0..1010] of longint;
que :array[0..1010] of longint;
pre,other,len :array[0..170010] of longint;
num :array[0..25,0..25] of longint;
map,jump :array[0..25,0..25] of char;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;

procedure connect(x,y,z:longint);
begin
inc(l);
pre[l]:=last[x];
last[x]:=l;
other[l]:=y;
len[l]:=z;
end;

function bfs:boolean;
var
p,q,cur,h,tl:longint;
begin
fillchar(dis,sizeof(dis),0);
h:=0;tl:=1;
que[1]:=ss;dis[ss]:=1;
while (h<>tl) do
begin
h:=h mod 805+1;
cur:=que[h];
q:=last[cur];
while (q<>0) do
begin
p:=other[q];
if (len[q]>0) and (dis[p]=0) then
begin
tl:=tl mod 805+1;
que[tl]:=p;
dis[p]:=dis[cur]+1;
if p=st then exit(true);
end;
q:=pre[q];
end;
end;
exit(false);
end;

function dinic(x,flow:longint):longint;
var
p,q:longint;
rest,tt:longint;
begin
if (x=st) then exit(flow);
rest:=flow;
q:=last[x];
while (q<>0) do
begin
p:=other[q];
if (dis[x]+1=dis[p]) and (len[q]>0) and (rest>0) then
begin
tt:=dinic(p,min(rest,len[q]));
dec(rest,tt);
dec(len[q],tt);
inc(len[q xor 1],tt);
end;
q:=pre[q];
end;
exit(flow-rest);
end;

begin
readln(n,m,d);l:=1;
for i:=1 to n do
begin
readln(s);
for j:=1 to m do map[i,j]:=s[j];
end;
for i:=1 to n do
begin
readln(s);
for j:=1 to m do jump[i,j]:=s[j];
end;
//
ss:=n*m*2+1;st:=ss+1;
for i:=1 to n do
for j:=1 to m do num[i,j]:=m*(i-1)+j;
//
sum:=0;
for i:=1 to n do
for j:=1 to m do
if (jump[i,j]='L') then
begin
connect(ss,num[i,j],1);
connect(num[i,j],ss,0);
inc(sum);
end;
//
for i:=1 to n do
for j:=1 to m do
if (map[i,j]<>'0') then
begin
for ii:=1 to n do
for jj:=1 to m do
if ((i-ii)*(i-ii)+(j-jj)*(j-jj)<=d*d) and ((i<>ii) or (j<>jj)) then
begin
connect(num[i,j]+n*m,num[ii,jj],maxlongint div 10);
connect(num[ii,jj],num[i,j]+n*m,0);
end;
end;
//
for i:=1 to d do
for j:=1 to m do
if (map[i,j]<>'0') then
begin
connect(num[i,j]+n*m,st,maxlongint div 10);
connect(st,num[i,j]+n*m,0);
end;
for i:=1 to n do
for j:=1 to d do
if (map[i,j]<>'0') then
begin
connect(num[i,j]+n*m,st,maxlongint div 10);
connect(st,num[i,j]+n*m,0);
end;
for i:=n-d+1 to n do
for j:=1 to m do
if (map[i,j]<>'0') then
begin
connect(num[i,j]+n*m,st,maxlongint div 10);
connect(st,num[i,j]+n*m,0);
end;
for i:=1 to n do
for j:=m-d+1 to m do
if (map[i,j]<>'0') then
begin
connect(num[i,j]+n*m,st,maxlongint div 10);
connect(st,num[i,j]+n*m,0);
end;
//
for i:=1 to n do
for j:=1 to m do
if (map[i,j]<>'0') then
begin
val(map[i,j],x);
connect(num[i,j],num[i,j]+n*m,x);
connect(num[i,j]+n*m,num[i,j],0);
end;
//
ans:=0;
while bfs do inc(ans,dinic(ss,maxlongint div 10));
writeln(sum-ans);
end.
——by Eirlys

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj 网络流