BZOJ 1189 HNOI2007 紧急疏散evacuate 二分答案+最大流

来源:互联网 发布:java 获取post还是get 编辑:程序博客网 时间:2024/05/16 10:00

题目大意:给定一个m*n的地图,每个点有可能是空地、墙或者出口,每个空地初始站着一个人,每一时刻可以向周围走1格,门每一时刻只能通过一个人,求最短多少时间后所有人可以撤离

首先从每个出口出发开始广搜,得到每个空地到所有出口的距离

然后二分答案,每次建图如下:

从源点向每个空地一条流量为1的边

如果一个空地能在规定时间到达某个出口,就从这个空地出发向该出口链接一条流量为1的边

每个出口向汇点连接一条流量为时间的边

然后跑最大流验证即可 注意图有不连通的情况 所以广搜要清初值(这个没人会忘吧QAQ 但是我卡了一晚上……)

那么问题来了:

会不会有这样的情况,规定时间为2,而两个人同时在时间2到达门口,于是堵住了,但是跑出来的的答案却是2呢?

……很不幸地告诉你 会

比如说这组样例:


这个样例的答案是3 但是这样建图跑出来是2

这幅图中间下方的人有两个选择:从上面逃生或从下面逃生

如果从下面逃生 那么左右两个人到上面的距离都是3 2时间内无法逃出

如果从上面逃生 那么两侧的人就会同时在时间2到达下侧出口 于是就愉快地卡住了~~

无视吧。。。不考虑这个这题还是能做的。。。。。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 30#define S abcd(0,0)#define T abcd(29,29)#define INF 0x3f3f3f3fusing namespace std;typedef pair<int,int> abcd;template<typename Temp>class Reader{    private:        Temp xx[M][M];    public:         Temp& operator [] (abcd x)        {            return xx[x.first][x.second];        }        Temp* operator [] (int x)        {            return xx[x];        }        inline void Clear(int x)        {            memset(xx,x,sizeof xx);        }};struct edge{    abcd to;    int f,next;}table[100100];Reader<int>head;int tot=1;const int dx[]={0,0,1,-1};const int dy[]={1,-1,0,0};int m,n,cnt,per;char s[M];abcd exi[M<<2];Reader<int>f[M<<2];Reader<int>map;Reader<int>dpt;void Add(abcd x,abcd y,int z){    table[++tot].to=y;    table[tot].f=z;    table[tot].next=head[x];    head[x]=tot;}void Link(abcd x,abcd y,int z){    Add(x,y,z);    Add(y,x,0);}void BFS(abcd start,Reader<int>&f){    static abcd q[1<<16];    int i,r=0,h=0;    f.Clear(0x3f);q[++r]=start;f[start]=0;    while(r!=h)    {        abcd x=q[++h];        for(i=0;i<4;i++)        {            abcd y(x.first+dx[i],x.second+dy[i]);            if(y.first<=0||y.second<=0||y.first>m||y.second>n)                continue;            if(map[y]||f[y]!=0x3f3f3f3f) continue;            f[y]=f[x]+1;            q[++r]=y;        }    }}bool BFS(){    static abcd q[1<<16];    int i,r=0,h=0;    dpt.Clear(-1);    q[++r]=S;dpt[S]=1;    while(r!=h)    {        abcd x=q[++h];        for(i=head[x];i;i=table[i].next)            if(table[i].f&&!~dpt[table[i].to])            {                dpt[table[i].to]=dpt[x]+1;                q[++r]=table[i].to;                if(table[i].to==T)                    return true;            }    }    return false;}int Dinic(abcd x,int flow){    int i,left=flow;    if(x==T) return flow;    for(i=head[x];i&&left;i=table[i].next)        if(table[i].f&&dpt[table[i].to]==dpt[x]+1)        {            int temp=Dinic(table[i].to,min(left,table[i].f) );            if(!temp) dpt[table[i].to]=-1;            left-=temp;            table[i].f-=temp;            table[i^1].f+=temp;        }    return flow-left;}bool Judge(int x){    int i,j,k,re=0;    head.Clear(0),tot=1;    for(i=1;i<=m;i++)        for(j=1;j<=n;j++)            if(map[i][j]==0)            {                Link(S,abcd(i,j),1);                for(k=1;k<=cnt;k++)                    if(f[k][i][j]<=x)                        Link(abcd(i,j),exi[k],1);            }    for(k=1;k<=cnt;k++)        Link(exi[k],T,x);    while( BFS() )        re+=Dinic(S,INF);    return re==per;}int Bisection(){    int l=0,r=m*n;    while(l+1<r)    {        int mid=l+r>>1;        if( Judge(mid) )            r=mid;        else            l=mid;    }    if( Judge(l) )        return l;    return r;}int main(){         //freopen("evacuate.in","r",stdin);    //freopen("evacuate.out","w",stdout);         int i,j;    cin>>m>>n;    for(i=1;i<=m;i++)    {        scanf("%s",s+1);        for(j=1;j<=n;j++)            switch(s[j])            {                case 'D':                    exi[++cnt]=abcd(i,j);                case 'X':                    map[i][j]=1;                    break;                case '.':                    map[i][j]=0;                    ++per;                    break;            }    }    for(i=1;i<=cnt;i++)        BFS(exi[i],f[i]);    int ans=Bisection();    if(ans==m*n) puts("impossible");    else cout<<ans<<endl;    return 0;}


0 0
原创粉丝点击