zoukankan      html  css  js  c++  java
  • BZOJ1189: [HNOI2007]紧急疏散evacuate(二分答案,最大流)

    Description

    发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一
    块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门
    一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都
    可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是
    说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的
    位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本
    不可能。

    Input

    第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,
    以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

    Output

    只有一个整数K,表示让所有人安全撤离的最短时间,
    如果不可能撤离,那么输出'impossible'(不包括引号)。

    Sample Input

    5 5
    XXXXX
    X...D
    XX.XX
    X..XX
    XXDXX

    Sample Output

    3
    解题思路:
    考虑每个点到每个门的最短路一定所以先Bfs/Dijstra一遍得到每个点到每个门到最短距离。
    考虑随着时间的推移,每个点能够到达的门也就越多,所以可以说是动态加边。
    这时的正确方法是二分答案,建图网络流。
    显然是源点连人,在时间允许的情况下人连门,容量为1。门连汇点,容量为T。
    这样做理论上是很好的,但是有一个问题,那就是本题的特殊性,每个格子可以重复走人但是门只能一个一个出。
    这就十分不和谐了,因为上面的做法并不能处理两个人同时到达的情况。
    考虑一个问题,到底是什么性质没有被体现导致建图瑕疵。
    这里可以认为门在T时刻关闭,那么本质上每个人都有一个剩余时间,假如说一起到然后一个一个出,
    这里的问题就是假如说一起到的人比较多,假如说大于T那么一定不能全部出去。
    所以需要有一个条件来限制每个人到达时还剩多少时间,换句话说,需要表现他究竟是什么时间到达的。
    这样,将每个门拆成T个点,代表该时刻到达的门(相当于给门分层)。
    每个点向到达时间的门连边,每层门向下一层连流量为$inf$的边。
    跑最大流验证就好了。
    代码:
      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 const int oo=0x3f3f3f3f;
      6 struct int_2{int TIME;int NO;};
      7 struct pnt{
      8     int hd;
      9     int lyr;
     10     int now;
     11 }p[1000000];
     12 struct ent{
     13     int twd;
     14     int vls;
     15     int lst;
     16     int his;
     17 }e[5000000];
     18 struct OVO{
     19     int_2 pro;
     20     int i;
     21     int j;
     22 };
     23 int cnt;
     24 int n,m;
     25 int s,t;
     26 int pnum;
     27 char tmp[100];
     28 int no[21][21];
     29 int mp[21][21];
     30 bool vis[21][21];
     31 bool hvv[21][21];
     32 std::queue<int>Q;
     33 std::queue<OVO>P;
     34 std::vector<int>T[1000];
     35 std::vector<int_2>dr[21][21];
     36 void ade(int f,int t,int v)
     37 {
     38     cnt++;
     39     e[cnt].twd=t;
     40     e[cnt].vls=v;
     41     e[cnt].his=v;
     42     e[cnt].lst=p[f].hd;
     43     p[f].hd=cnt;
     44     return ;
     45 }
     46 bool bfs(void)
     47 {
     48     for(int i=1;i<=n;i++)
     49     {
     50         for(int j=1;j<=m;j++)
     51         {
     52             if(mp[i][j]==2)
     53             {
     54                 while(!P.empty())
     55                     P.pop();
     56                 P.push((OVO){(int_2){0,no[i][j]},i,j});
     57                 while(!P.empty())
     58                 {
     59                     OVO x=P.front();
     60                     P.pop();
     61                     int ii=x.i;
     62                     int jj=x.j;
     63                     if(vis[ii][jj])
     64                         continue;
     65                     vis[ii][jj]=true;
     66                     if(mp[ii][jj]==1)
     67                         dr[ii][jj].push_back(x.pro);
     68                     x.pro.TIME++;
     69                     OVO y;
     70                     y=x;
     71                     y.i++;
     72                     if(y.i<=n)
     73                     {
     74                         if(mp[y.i][y.j]==1)
     75                         {
     76                             P.push(y);
     77                         }
     78                     }
     79                     y=x;
     80                     y.i--;
     81                     if(y.i>0)
     82                     {
     83                         if(mp[y.i][y.j]==1)
     84                         {
     85                             P.push(y);
     86                         }
     87                     }
     88                     y=x;
     89                     y.j++;
     90                     if(y.j<=m)
     91                     {
     92                         if(mp[y.i][y.j]==1)
     93                         {
     94                             P.push(y);
     95                         }
     96                     }
     97                     y=x;
     98                     y.j--;
     99                     if(y.j>0)
    100                     {
    101                         if(mp[y.i][y.j]==1)
    102                         {
    103                             P.push(y);
    104                         }
    105                     }
    106                 }
    107                 for(int ii=1;ii<=n;ii++)
    108                 {
    109                     for(int jj=1;jj<=m;jj++)
    110                     {
    111                         if(vis[ii][jj])
    112                             hvv[ii][jj]=true;
    113                         vis[ii][jj]=false;
    114                     }
    115                 }
    116             }
    117         }
    118     }
    119     for(int i=1;i<=n;i++)
    120     {
    121         for(int j=1;j<=m;j++)
    122         {
    123             if(!hvv[i][j]&&mp[i][j]==1)
    124                 return true;
    125         }
    126     }
    127     return false;
    128 }
    129 bool Bfs(void)
    130 {
    131     while(!Q.empty())Q.pop();
    132     for(int i=1;i<=t;i++)
    133         p[i].lyr=0;
    134     p[s].lyr=1;
    135     Q.push(s);
    136     while(!Q.empty())
    137     {
    138         int x=Q.front();
    139         Q.pop();
    140         for(int i=p[x].hd;i;i=e[i].lst)
    141         {
    142             int to=e[i].twd;
    143             if(p[to].lyr==0&&e[i].vls>0)
    144             {
    145                 p[to].lyr=p[x].lyr+1;
    146                 if(to==t)
    147                     return true;
    148                 Q.push(to);
    149             }
    150         }
    151     }
    152     return false;
    153 }
    154 int Dfs(int x,int fll)
    155 {
    156     if(x==t)
    157         return fll;
    158     for(int& i=p[x].now;i;i=e[i].lst)
    159     {
    160         int to=e[i].twd;
    161         if(p[to].lyr==p[x].lyr+1&&e[i].vls>0)
    162         {
    163             int ans=Dfs(to,std::min(fll,e[i].vls));
    164             if(ans>0)
    165             {
    166                 e[i].vls-=ans;
    167                 e[((i-1)^1)+1].vls+=ans;
    168                 return ans;
    169             }
    170         }
    171     }
    172     return 0;
    173 }
    174 int Dinic(void)
    175 {
    176     int ans=0;
    177     while(Bfs())
    178     {
    179         for(int i=1;i<=t;i++)
    180             p[i].now=p[i].hd;
    181         int dlt;
    182         while(dlt=Dfs(s,oo))
    183             ans+=dlt;
    184     }
    185     return ans;
    186 }
    187 bool Check(int x)
    188 {
    189     for(int i=1;i<=t;i++)
    190         p[i].hd=0;
    191     cnt=0;
    192     int lcnt=n*m;
    193     for(int i=1;i<=n;i++)
    194         for(int j=1;j<=m;j++)
    195             if(mp[i][j]==2)
    196             {
    197                 T[no[i][j]].clear();
    198                 for(int k=0;k<=x;k++)
    199                     T[no[i][j]].push_back(++lcnt);
    200             }
    201     s=lcnt+1;
    202     t=s+1;
    203     for(int i=1;i<=n;i++)
    204     {
    205         for(int j=1;j<=m;j++)
    206         {
    207             if(mp[i][j]==1)
    208             {
    209                 ade(s,no[i][j],1);
    210                 ade(no[i][j],s,0);
    211                 for(int k=0;k<dr[i][j].size();k++)
    212                 {
    213                     if(dr[i][j][k].TIME<=x)
    214                     {
    215                         ade(no[i][j],T[dr[i][j][k].NO][dr[i][j][k].TIME],1);
    216                         ade(T[dr[i][j][k].NO][dr[i][j][k].TIME],no[i][j],0);
    217                     }
    218                 }
    219             }else if(mp[i][j]==2)
    220             {
    221                 for(int k=0;k<=x;k++)
    222                 {
    223                     ade(T[no[i][j]][k],t,1);
    224                     ade(t,T[no[i][j]][k],0);
    225                     if(k!=x)
    226                     {
    227                         ade(T[no[i][j]][k],T[no[i][j]][k+1],oo);
    228                         ade(T[no[i][j]][k+1],T[no[i][j]][k],0);
    229                     }
    230                 }
    231             }
    232         }
    233     }
    234     return pnum==Dinic();
    235 }
    236 int main()
    237 {
    238 //    freopen("a.in","r",stdin);
    239     scanf("%d%d",&n,&m);
    240     for(int i=1;i<=n;i++)
    241     {
    242         scanf("%s",tmp+1);
    243         for(int j=1;j<=m;j++)
    244         {
    245             no[i][j]=++cnt;
    246             if(tmp[j]=='X')
    247                 mp[i][j]=0;
    248             if(tmp[j]=='.')
    249                 mp[i][j]=1,
    250                 pnum++;
    251             if(tmp[j]=='D')
    252                 mp[i][j]=2;
    253         }
    254     }
    255     cnt=0;
    256     if(bfs())
    257     {
    258         puts("impossible");
    259         return 0;
    260     }
    261     int l=0,r=1000;
    262     int ans;
    263     while(l<=r)
    264     {
    265         int mid=(l+r)>>1;
    266         if(Check(mid))
    267         {
    268             ans=mid;
    269             r=mid-1;
    270         }else
    271             l=mid+1;
    272     }
    273     printf("%d
    ",ans);
    274     return 0;
    275 }
  • 相关阅读:
    Oracle11gR2导入导出实战之物化视图prebuilt
    Oracle11gr2_ADG管理之switchover补充
    Oracle11gR2--手工建库&dbca建库
    Oracle11gr2_ADG管理之在备库上模拟failover的过程实战
    自己写个验证码类
    隐藏字符 BOM
    jquery与自己写的js文件冲突解决办法
    javaBean
    序列化
    UML
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10238928.html
Copyright © 2011-2022 走看看