bzoj 1066 最大流

将每个石柱拆成两个点,分别是进入的和出去的,两个点之间连石柱的高度

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

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

/**************************************************************
    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.
原文地址:https://www.cnblogs.com/BLADEVIL/p/3489045.html