zoukankan      html  css  js  c++  java
  • bzoj1189

    初看这题好像跟我mincost第一题很像,多了点门其实最短路/bfs与处理一下就可以了

    但是门只能容纳一个人

    所以,也就是说,费用是变的,怎么做?

    仔细想想,费用流好像不能处理费用改变的

    扔掉费用流,首先决策具有单调性,二分!

    当我们确定了时间之后,我们怎么快速的判断可行呢?

    由于门每分钟只能容纳一个人,也就是说,在这分钟内这个门只能被一个人匹配

    不禁想到了最大流/二分图匹配,暴力将每个门拆成对应时间点

    每个人对应能走的门连边然后匈牙利即可

    到这问题好像解决了(实际上也解决了);

    但我写着写着发现一个问题

    一开始的预处理,似乎不能简单的求每点到每个门的最短距离

    因为看起来有的门能到,实际却到不了

    比如

    XXDDX

    XXX.X

    X...X

    X...X

    XXXXX

    比如(1,3)的门是根本走不到的,被另一个门挡住了

    而且这是会影响结果的(在一个门被堵住,肯定要分流去另一个门)

    但我也没管,后来发现数据里好像也没这种情况(……)

    就这样吧

    一般的,费用流的费用都是不变的吧,否则都应该转化为二分+最大流判定吧

    为了方便我写了二分图匹配快一些

      1 const dx:array[1..4] of integer=(0,0,-1,1);
      2       dy:array[1..4] of integer=(1,-1,0,0);
      3       inf=10000007;
      4 type node=record
      5        point,next:longint;
      6      end;
      7 
      8 var a,map,dis:array[0..1010,0..1010] of longint;
      9     q:array[0..2000010] of longint;
     10     cx,d,p,b:array[0..1010] of longint;    
     11     cy:array[0..1001000] of longint;     //注意二分图另一个点集规模
     12     edge:array[0..5000010] of node;
     13     v:array[0..1001010] of boolean;
     14     k,ans,len,pep,sum,x,y,l,r,mid,n,m,t,i,j:longint;
     15     ch:char;
     16 
     17 procedure add(x,y:longint);
     18   begin
     19     inc(len);
     20     edge[len].point:=y;
     21     edge[len].next:=p[x];
     22     p[x]:=len;
     23   end;
     24 
     25 procedure spfa(k:longint);
     26   var s,i,x,f,r:longint;
     27   begin
     28     f:=1;
     29     r:=1;
     30     for i:=1 to t do
     31       d[i]:=inf;
     32     s:=b[k];
     33     d[s]:=0;
     34     fillchar(v,sizeof(v),false);
     35     v[s]:=true;
     36     q[1]:=s;
     37     while f<=r do
     38     begin
     39       x:=q[f];
     40       v[x]:=false;
     41       for i:=1 to t do
     42         if map[x,i]>0 then
     43           if d[i]>d[x]+map[x,i] then
     44           begin
     45             d[i]:=d[x]+map[x,i];
     46             if not v[i] then
     47             begin
     48               inc(r);
     49               q[r]:=i;
     50               v[i]:=true;
     51             end;
     52           end;
     53       inc(f);
     54     end;
     55     for i:=1 to pep do
     56       dis[i,k]:=d[i];
     57   end;
     58 
     59 function dfs(x:longint):boolean;
     60   var i,j:longint;
     61   begin
     62     i:=p[x];
     63     while i<>-1 do
     64     begin
     65       j:=edge[i].point;
     66       if not v[j] then
     67       begin
     68         v[j]:=true;
     69         if (cy[j]=-1) or dfs(cy[j]) then
     70         begin
     71           cy[j]:=x;
     72           cx[x]:=j;
     73           exit(true);
     74         end;
     75       end;
     76       i:=edge[i].next;
     77     end;
     78     exit(false);
     79   end;
     80 
     81 function check(k:longint):boolean;
     82   var s,i,j,w,z:longint;
     83   begin
     84     len:=0;
     85     fillchar(p,sizeof(p),255);
     86     for i:=1 to pep do
     87     begin
     88       for j:=1 to sum do
     89         if dis[i,j]<=k then
     90         begin
     91           for w:=0 to k-dis[i,j] do
     92           begin
     93             z:=(j-1)*k+dis[i,j]+w;        //暴力拆点
     94             add(i,z);
     95           end;
     96         end;
     97     end;
     98     fillchar(cx,sizeof(cx),255);
     99     fillchar(cy,sizeof(cy),255);
    100     for i:=1 to pep do
    101     begin
    102       fillchar(v,sizeof(v),false);
    103       if not dfs(i) then exit(false);     //匹配
    104     end;
    105     exit(true);
    106   end;
    107 
    108 begin
    109   readln(n,m);
    110   fillchar(a,sizeof(a),0);
    111   for i:=1 to n do
    112   begin
    113     for j:=1 to m do
    114     begin
    115       read(ch);
    116       if ch='.' then
    117       begin
    118         inc(pep);
    119         a[i,j]:=pep;
    120       end
    121       else if ch='D' then
    122       begin
    123         inc(sum);
    124         a[i,j]:=-sum;
    125       end;
    126     end;
    127     readln;
    128   end;
    129   sum:=0;
    130   for i:=1 to n do
    131     for j:=1 to m do
    132       if a[i,j]<0 then
    133       begin
    134         inc(sum);
    135         a[i,j]:=abs(a[i,j])+pep;
    136         b[sum]:=a[i,j];
    137       end;
    138 
    139   for i:=1 to n do                  //其实是有问题的预处理
    140     for j:=1 to m do
    141       if a[i,j]>0 then
    142       begin
    143         for k:=1 to 4 do
    144         begin
    145           x:=i+dx[k];
    146           y:=j+dy[k];
    147           if a[x,y]>0 then
    148           begin
    149             map[a[i,j],a[x,y]]:=1;
    150             map[a[i,j],a[x,y]]:=1;
    151           end;
    152         end;
    153       end;
    154   t:=pep+sum;
    155 
    156   for i:=1 to sum do
    157     spfa(i);                   
    158   l:=1;
    159   r:=1000;
    160   ans:=0;
    161   while l<=r do
    162   begin
    163     mid:=(l+r) shr 1;
    164     if check(mid) then
    165     begin
    166       ans:=mid;
    167       r:=mid-1;
    168     end
    169     else l:=mid+1;
    170   end;
    171   if ans=0 then writeln('impossible')
    172   else writeln(ans);
    173 end.
    View Code
  • 相关阅读:
    cocos代码研究(24)Widget子类PageView学习笔记
    cocos代码研究(23)Widget子类ScrollView学习笔记
    cocos代码研究(22)Widget子类Layout学习笔记
    JavaScript:学习笔记(5)——箭头函数=>以及实践
    顽石系列:CSS实现垂直居中的五种方法
    算法:红黑树
    Vue:实践学习笔记(3)——组件使用
    Java进阶学习:将文件上传到七牛云中
    LeetCode:下一个排列【31】
    Linux:Ubuntu下部署Web运行环境
  • 原文地址:https://www.cnblogs.com/phile/p/4473255.html
Copyright © 2011-2022 走看看