您的位置:首页 > 其它

bzoj 1066 最大流

2013-12-24 14:52 239 查看
将每个石柱拆成两个点,分别是进入的和出去的,两个点之间连石柱的高度

然后每个出去的点连别的石柱的进去的点,

源点连所有蜥蜴所在柱子,每个能跳出去的连汇点,然后最大流就行了

/**************************************************************
Problem: 1066
User: BLADEVIL
Language: Pascal
Result: Accepted
Time:48 ms
Memory:2748 kb
****************************************************************/

//By BLADEVIL
var
r, c, d                             :longint;
map, jump                           :array[0..300,0..300] of char;
pre, other, len                     :array[0..100010] of longint;
last                                :array[0..10100] of longint;
num                                 :array[0..300,0..300] of longint;
source, sink                        :longint;
l                                   :longint;
que, dis                            :array[0..100000] of longint;
ans, sum                            :longint;

function min(a,b:longint):longint;
begin
if a>b then min:=b else min:=a;
end;

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

procedure init;
var
i, j, ii, jj                        :longint;
k                                   :longint;

begin
readln(r,c,d); l:=1;
for i:=1 to r do
begin
for j:=1 to c do
read(map[i,j]);
readln;
end;

for i:=1 to r do
begin
for j:=1 to c do read(jump[i,j]);
readln;
end;

for i:=1 to r do
for j:=1 to c do num[i,j]:=c*(i-1)+j;
source:=2*r*c+2; sink:=source+1;

for i:=1 to r do
for j:=1 to c do
if jump[i,j]='L' then
begin
connect(source,num[i,j],1);
connect(num[i,j],source,0);
inc(sum);
end;

for i:=1 to r do
for j:=1 to c do
if map[i,j]<>'0' then
begin
for ii:=1 to r do
for jj:=1 to c do
//if (i<>ii) or (j<>jj) then
begin
if (sqrt((i-ii)*(i-ii)+(j-jj)*(j-jj))<=d) then
begin
connect(num[i,j]+r*c,num[ii,jj],maxlongint div 10);
connect(num[ii,jj],num[i,j]+r*c,0);
end;
end;
end;

for i:=1 to d do
for j:=1 to c do
if map[i,j]<>'0' then
begin
connect(num[i,j]+r*c,sink,maxlongint div 10);
connect(sink,num[i,j]+r*c,0);
end;
for i:=r-d+1 to r do
for j:=1 to c do
if map[i,j]<>'0' then
begin
connect(num[i,j]+r*c,sink,maxlongint div 10);
connect(sink,num[i,j]+r*c,0);
end;
for i:=1 to r do
for j:=1 to d do
if map[i,j]<>'0' then
begin
connect(num[i,j]+r*c,sink,maxlongint div 10);
connect(sink,num[i,j]+r*c,0);
end;

for i:=1 to r do
for j:=c-d+1 to c do
if map[i,j]<>'0' then
begin
connect(num[i,j]+r*c,sink,maxlongint div 10);
connect(sink,num[i,j]+r*c,0);
end;
for i:=1 to r do
for j:=1 to c do
if map[i,j]<>'0' then
begin
k:=ord(map[i,j])-48;
connect(num[i,j],num[i,j]+r*c,k);
connect(num[i,j]+r*c,num[i,j],0);
end;
end;

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

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

procedure main;
begin
while bfs do
ans:=ans+dinic(source,maxlongint div 10);
writeln(sum-ans);
end;

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