首先我们可以二分一个答案时间T,这样就将最优性问题

转化为了判定性问题。下面我们考虑对于已知的T的判定

对于矩阵中所有的空点bfs一次,得出来每个点到门的距离,

然后连接空点和每个能在t时间内到达的门一条边,容量为1,

之后连接源和每个空点一条边,容量为1,门连接汇边,容量为t。

判断最大流是否满流就好了。

/**************************************************************
    Problem:
    User: BLADEVIL
    Language: Pascal
    Result: Accepted
    Time: ms
    Memory: kb
****************************************************************/
 
//By BLADEVIL
type
    rec                         =record
        x, y                    :longint;
    end;
 
var
    n, m                        :longint;
    pre, other, len, time       :array[..] of longint;
    last                        :array[..] of longint;
    l                           :longint;
    que1                        :array[..] of rec;
    dis                         :array[..,..] of longint;
    go                          :array[..,..] of longint;
    num                         :array[..,..] of longint;
    source, sink                :longint;
    sum                         :longint;
    map                         :array[..,..] of char;
    que, d                      :array[..] of longint;
     
function min(a,b:longint):longint;
begin
    if a>b then min:=b else min:=a;
end;
     
procedure connect(a,b,c,d:longint);
begin
    inc(l);
    pre[l]:=last[a];
    last[a]:=l;
    other[l]:=b;
    len[l]:=c;
    time[l]:=d;
end;
     
procedure make(a,b:longint);
var
    h, t, curx, cury, nx, ny    :longint;
    i, j                        :longint;
    f                           :boolean;
     
begin
    connect(source,num[a,b],,);
    connect(num[a,b],source,,);
    fillchar(dis,sizeof(dis),);
    dis[a,b]:=; que1[].x:=a; que1[].y:=b;
    h:=; t:=;
    while h<t do
    begin
        inc(h);
        curx:=que1[h].x; cury:=que1[h].y;
        for i:= to do
        begin
            nx:=curx+go[,i]; ny:=cury+go[,i];
            if (nx<) or (nx>n) or (ny<) or (ny>m) then continue;
            if dis[nx,ny]<> then continue;
            if map[nx,ny]='X' then continue;
            inc(t);
            que1[t].x:=nx; que1[t].y:=ny;
            dis[nx,ny]:=dis[curx,cury]+;
        end;
    end;
    f:=false;
    for i:= to n do
        for j:= to m do
        if map[i,j]='D' then
            if dis[i,j]<> then
            begin
                f:=true;
                connect(num[a,b],num[i,j],,dis[i,j]-);
                connect(num[i,j],num[a,b],,dis[i,j]-);
            end;
    if not f then
    begin
        writeln('impossible');
        halt;
    end;
end;
     
procedure init;
var
    i, j                        :longint;
begin
    go[,]:=-; go[,]:=; go[,]:=; go[,]:=-;
    readln(n,m);
    for i:= to n do
    begin
        for j:= to m do read(map[i,j]);
        readln;
    end;
     
    for i:= to n do
        for j:= to m do num[i,j]:=(i-)*m+j;
     
    source:=*n*m+; sink:=source+;
    l:=;
    for i:= to n do
        for j:= to m do
            if map[i,j]='.' then
            begin
                make(i,j);
                inc(sum);
            end;
             
    for i:= to n do
        for j:= to m do
            if map[i,j]='D' then
            begin
                connect(num[i,j],sink,,);
                connect(sink,num[i,j],,);
            end;
end;
 
function bfs(up:longint):boolean;
var
    q, p                        :longint;
    h, t, cur                   :longint;
begin
    fillchar(d,sizeof(d),);
    que[]:=source; h:=; t:=;
    d[source]:=;
    while h<t do
    begin
        inc(h);
        cur:=que[h];
        q:=last[cur];
        while q<> do
        begin
            if (len[q]>) and (time[q]<=up) then
            begin
                p:=other[q];
                if (d[p]=) then
                begin
                    inc(t);
                    que[t]:=p;
                    d[p]:=d[cur]+;
                    if p=sink then exit(true);
                end;
            end;
            q:=pre[q];
        end;
    end;
    exit(false);
end;
 
function dinic(x,flow,up:longint):longint;
var
    tmp, rest                   :longint;
    q, p                        :longint;
begin
    rest:=flow;
    if x=sink then exit(flow);
    q:=last[x];
    while q<> do
    begin
        p:=other[q];
        if (len[q]>) and (time[q]<=up) and (rest>) and (d[x]=d[p]-) then
        begin
            tmp:=dinic(p,min(len[q],rest),up);
            dec(rest,tmp);
            dec(len[q],tmp);
            inc(len[q xor ],tmp);
        end;
        q:=pre[q];
    end;
    exit(flow-rest);
end;
 
function judge(mid:longint):boolean;
var
    q                           :longint;
    tot                         :longint;
    i                           :longint;
begin
    q:=last[sink];
    while q<> do
    begin
        len[q]:=;
        len[q xor ]:=mid;
        q:=pre[q];
    end;
    tot:=;
    while bfs(mid) do
        tot:=tot+dinic(source,maxlongint,mid);
    for i:= to l do if i mod = then
    begin
        inc(len[i],len[i xor ]);
        len[i xor ]:=;
    end;
    if tot<sum then exit(false) else exit(true);
end;
 
procedure main;
var
    l, r, mid, ans              :longint;
begin
    l:=; r:=;
    while l<=r do
    begin
        mid:=(l+r) div ;
        if judge(mid) then
        begin
            ans:=mid;
            r:=mid-;
        end else l:=mid+;
    end;
    writeln(ans);
end;
 
begin
    init;
    main;
end.

bzoj 1189 二分+最大流判定的更多相关文章

  1. bzoj 1305 二分+最大流判定|贪心

    首先我们二分一个答案mid,在判定是否能举办mid次,那么对于每个次我们可以用最大流根据是否满流(流量为n*mid)来判定,对于每个点我们拆成两个点,分别表示这个人要和他喜欢和不喜欢的人一起跳舞,那么 ...

  2. bzoj 1189 二分+最大流

    题目传送门 思路: 先预处理出每个人到每扇门的时间,用门作为起点进行bfs处理. 然后二分时间,假设时间为x,将每扇门拆成1到x,x个时间点,表示这扇门有几个时间点是可以出去的.对于一扇门,每个时间点 ...

  3. BZOJ-1822 Frozen Nova 冷冻波 计(jie)算(xi)几何+二分+最大流判定+经典建图

    这道逼题!感受到了数学对我的深深恶意(#‵′).... 1822: [JSOI2010]Frozen Nova 冷冻波 Time Limit: 10 Sec Memory Limit: 64 MB S ...

  4. BZOJ 1189 二分匹配 || 最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1155  Solved: 420[Submi ...

  5. uvalive 3231 Fair Share 公平分配问题 二分+最大流 右边最多流量的结点流量尽量少。

    /** 题目: uvalive 3231 Fair Share 公平分配问题 链接:https://vjudge.net/problem/UVALive-3231 题意:有m个任务,n个处理器,每个任 ...

  6. poj 2391 Ombrophobic Bovines 最短路 二分 最大流 拆点

    题目链接 题意 有\(n\)个牛棚,每个牛棚初始有\(a_i\)头牛,最后能容纳\(b_i\)头牛.有\(m\)条道路,边权为走这段路所需花费的时间.问最少需要多少时间能让所有的牛都有牛棚可待? 思路 ...

  7. HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    ...

  8. HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流

    二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...

  9. hdu4560 不错的建图,二分最大流

    题意: 我是歌手 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Subm ...

随机推荐

  1. 如何批量转换 WordPress 文章分类

    可能建博之初,分类设置过于详细,后来想重新整理并删除一些分类项目,比如删除分类A,并将其中的所有文章划归到分类B中,手动修改文章的分类过于麻烦,有木有什么方法可以批量移动文章到另一个分类中呢? 网上闲 ...

  2. pthreads多线程数据采集

    以前使用curl的多线程并不是真正的多线程,只是一种模拟的多线程,现在使用pthreads来实现真正意义上的多线程. 下载: windows下: http://windows.php.net/down ...

  3. java8新特性笔记

    1.forEach(),遍历数据结构中的元素,括号内可以带一个闭包的方法 2.双冒号用法:forEach(this::doSchedule),如果运行环境是闭包,java允许使用双冒号的写法来直接调用 ...

  4. C++ string 转 char*

    string 转到 char* char name[20]; string sname=GatherName[n]; strcpy(name,sname.c_str());

  5. (转载)实现QQ侧滑边栏

    Android ViewDragHelper实现QQ侧滑边栏 移动手机版的QQ的左边侧栏,有一个特殊的交互设计效果:当用户手指向右或向左滑动时,QQ的左边会弹出或收缩一个侧滑的边栏.这种效果简单的做法 ...

  6. SQL 查询优化

    优化方法论: 分析实例级的等待. 联系等待和队列. 确定方案. 细化到数据/文件级. 细化到进程级. 优化索引/查询.

  7. C# 查询Windows Service 信息 ,所在目录 启动状态

    1.WMI简介WMI是英文Windows Management Instrumentation的简写,它的功能主要是:访问本地主机的一些信息和服务,可以管理远程计算机(当然你必须要拥有足够的权限),比 ...

  8. MVC的Filters(拦截过滤)的Error页面,支持Ajax报错

    报错拦截过滤到error页面 [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, A ...

  9. python 序列的方法

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 在快速教程中,我们了解了最基本的序列(sequence).回忆一下,序列包含有定值 ...

  10. python 函数对象(函数式编程 lambda、map、filter、reduce)、闭包(closure)

    1.函数对象 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 秉承着一切皆对象的理念,我们再次回头来看函数(function).函 ...