码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流

时间:2015-08-29 13:57:03      阅读:300      评论:0      收藏:0      [点我收藏+]

标签:

1189: [HNOI2007]紧急疏散evacuate

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1132  Solved: 412
[Submit][Status][Discuss]

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
 
 
题解:S-‘.‘-‘D‘-T;先从门bfs出每个‘.’点到门的距离,注意要每种情况都要计算所以开一个距离数组400*20*20+1,再二分时间为最后‘D’到T的容量;
技术分享
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
#include<cmath>
#include<map>
using namespace std ;
typedef long long ll;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
//******************************************************************
namespace NetFlow
{
    const int MAXN=100000,MAXM=1000000,inf=1e9;
    struct Edge
    {
        int v,c,f,nx;
        Edge() {}
        Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
    } E[MAXM];
    int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
    void init(int _n)
    {
        N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
    }
    void link(int u,int v,int c)
    {
        E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
        E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
    }
    int ISAP(int S,int T)
    {//S -> T
        int maxflow=0,aug=inf,flag=false,u,v;
        for (int i=0;i<N;++i)cur[i]=G[i],gap[i]=dis[i]=0;
        for (gap[S]=N,u=pre[S]=S;dis[S]<N;flag=false)
        {
            for (int &it=cur[u];~it;it=E[it].nx)
            {
                if (E[it].c>E[it].f&&dis[u]==dis[v=E[it].v]+1)
                {
                    if (aug>E[it].c-E[it].f) aug=E[it].c-E[it].f;
                    pre[v]=u,u=v; flag=true;
                    if (u==T)
                    {
                        for (maxflow+=aug;u!=S;)
                        {
                            E[cur[u=pre[u]]].f+=aug;
                            E[cur[u]^1].f-=aug;
                        }
                        aug=inf;
                    }
                    break;
                }
            }
            if (flag) continue;
            int mx=N;
            for (int it=G[u];~it;it=E[it].nx)
            {
                if (E[it].c>E[it].f&&dis[E[it].v]<mx)
                {
                    mx=dis[E[it].v]; cur[u]=it;
                }
            }
            if ((--gap[dis[u]])==0) break;
            ++gap[dis[u]=mx+1]; u=pre[u];
        }
        return maxflow;
    }
    bool bfs(int S,int T)
    {
        static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
        dis[S]=0; Q[0]=S;
        for (int h=0,t=1,u,v,it;h<t;++h)
        {
            for (u=Q[h],it=G[u];~it;it=E[it].nx)
            {
                if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
                {
                    dis[v]=dis[u]+1; Q[t++]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int u,int T,int low)
    {
        if (u==T) return low;
        int ret=0,tmp,v;
        for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
        {
            if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
            {
                if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
                {
                    ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
                }
            }
        }
        if (!ret) dis[u]=-1; return ret;
    }
    int dinic(int S,int T)
    {
        int maxflow=0,tmp;
        while (bfs(S,T))
        {
            memcpy(cur,G,sizeof(G[0])*N);
            while (tmp=dfs(S,T,inf)) maxflow+=tmp;
        }
        return maxflow;
    }
}
struct sss
{
    int x,y,t;
}hh[30][30];
int n,m;
int ss[4][2]={-1,0,0,-1,1,0,0,1};
int tim[405][30][30];
char mp[30][30];
int tot;
int cnt=0;
int xxx[401],yyy[401];
void bfss(int a,int b,int index)
{
    sss k,kk;
    queue<sss>q;
    k.x=a;
    k.y=b;
    k.t=0;
    q.push(k);
    while(!q.empty())
    {
        kk=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int xx=kk.x+ss[i][0];
            int yy=kk.y+ss[i][1];
            if(xx<=0||xx>n||yy<=0||yy>m)continue;
            if(mp[xx][yy]==X||mp[xx][yy]==D)continue;
            if(kk.t+1<tim[index][xx][yy]){
                tim[index][xx][yy]=kk.t+1;
                hh[xx][yy].x=a;
                hh[xx][yy].y=b;
                sss kkk;
                kkk.x=xx;
                kkk.y=yy;
                kkk.t=tim[index][xx][yy];

               // cout<<"feinds "<<tim[xx][yy]<<endl;return;
                q.push(kkk);
            }
        }
    }
}
using namespace NetFlow;
int juge(int r)
{
    init(3000);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
        {
            if(mp[i][j]==.)
                link(1000,(i-1)*m+j,1);
        }
    }
    for(int i=1;i<=cnt;i++)link(n*m+i,1001,r);
    for(int i=1;i<=cnt;i++)
    {
        for(int j=1;j<=n;j++){
            for(int k=1;k<=m;k++)
            {
                if(tim[n*m+i][j][k]<=r)link((j-1)*m+k,n*m+i,1);
            }
        }
    }
   // cout<<14<<endl;
    if(dinic(1000,1001)==tot)return 1;
    else return 0;
}
int main()
{

    scanf("%d%d",&n,&m);
    tot=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",mp[i]+1);
        for(int j=1;j<=m;j++)
        {
            if(mp[i][j]==D)
            {
                cnt++;
                xxx[cnt]=i;
                yyy[cnt]=j;
            }
            if(mp[i][j]==.)tot++;
        }
    }
   // cout<<"das "<<tot<<endl;
    memset(tim,127,sizeof(tim));
   // if(cnt==0){cout<<"impossible"<<endl;return 0;}
    for(int i=1;i<=cnt;i++)
    {
        bfss(xxx[i],yyy[i],n*m+i);
    }
    int l=0;
    int r=400;
    int ans=-1;
    while(l<r)
    {
        int mid=(l+r)>>1;
        if(juge(mid))
        {
            ans=mid;
            r=mid;
        }
        else l=mid+1;
    }
    if(ans==-1)cout<<"impossible"<<endl;
    else
    cout<<ans<<endl;
    return 0;
}
代码

 

BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流

标签:

原文地址:http://www.cnblogs.com/zxhl/p/4769007.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!