• P3191 [HNOI2007]紧急疏散EVACUATE


    传送门

    这一题很容易想到网络流

    一开始傻逼地模拟整个图每一个时间的情况,显然会爆炸

    发现我们只要考虑起点到门之间的距离,不用每一步只走一格

    所以直接 $BFS$ 预处理距离然后二分答案,网络流判断即可

    注意到了门就不能走了,所以门不能连边出去

    总的来说挺傻逼的一题...但是我就是没想到...

    某位不愿意透露姓名的神仙还有一种牛逼的费用流做法,代码极短$STO$

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int 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<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7,M=5e6+7,INF=1e9+7,xx[4]={0,1,0,-1},yy[4]={1,0,-1,0};
    int fir[N],from[M<<1],to[M<<1],val[M<<1],cntt=1;
    inline void add(int a,int b,int c)
    {
        from[++cntt]=fir[a]; fir[a]=cntt;
        to[cntt]=b; val[cntt]=c;
        from[++cntt]=fir[b]; fir[b]=cntt;
        to[cntt]=a; val[cntt]=0;
    }
    int n,m,tot,id[507][27][27],sum;
    int dep[N],S,T;
    queue <int> Q;
    bool BFS()
    {
        for(int i=0;i<=tot;i++) dep[i]=0;
        Q.push(S); dep[S]=1;
        while(!Q.empty())
        {
            int x=Q.front(); Q.pop();
            for(int i=fir[x];i;i=from[i])
            {
                int &v=to[i]; if(dep[v]||(!val[i])) continue;
                dep[v]=dep[x]+1; Q.push(v);
            }
        }
        return dep[T]>0;
    }
    int DFS(int x,int mxfl)
    {
        if(x==T||!mxfl) return mxfl;
        int fl=0,res;
        for(int i=fir[x];i;i=from[i])
        {
            int &v=to[i]; if(dep[v]!=dep[x]+1||!val[i]) continue;
            if( res=DFS(v,min(mxfl,val[i])) )
            {
                mxfl-=res; fl+=res;
                val[i]-=res; val[i^1]+=res;
                if(!mxfl) break;
            }
        }
        return fl;
    }
    char mp[233][233];
    int dis[27][27][27][27];
    struct dat{
        int x,y;
        dat (int a=0,int b=0) { x=a,y=b; }
    };
    queue <dat> q;
    void pre()
    {
        memset(dis,0x3f,sizeof(dis));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(mp[i][j]!='.') continue;
                q.push(dat(i,j)); dis[i][j][i][j]=0;
                while(!q.empty())
                {
                    dat u=q.front(); q.pop();
                    for(int k=0;k<4;k++)
                    {
                        int tx=u.x+xx[k],ty=u.y+yy[k];
                        if(tx<1||tx>n||ty<1||ty>m||mp[tx][ty]=='X'||dis[i][j][tx][ty]<M) continue;
                        dis[i][j][tx][ty]=dis[i][j][u.x][u.y]+1;
                        if(mp[tx][ty]!='D') q.push(dat(tx,ty));
                    }
                }
            }
    }
    bool check(int mid)
    {
        for(int i=0;i<=tot;i++) fir[i]=0; tot=1; S=0,T=1; cntt=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(mp[i][j]=='.') id[0][i][j]=++tot,add(S,tot,1);
        for(int t=1;t<=mid;t++)
            for(int k=1;k<=n;k++)
                for(int l=1;l<=m;l++)
                    if(mp[k][l]=='D') id[t][k][l]=++tot,add(tot,T,1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                if(mp[i][j]!='.') continue;
                for(int t=1;t<=mid;t++)
                    for(int k=1;k<=n;k++)
                        for(int l=1;l<=m;l++)
                            if(mp[k][l]=='D'&&dis[i][j][k][l]<=t) add(id[0][i][j],id[t][k][l],INF);
            }
        int now=0;
        while(BFS())
        {
            now+=DFS(S,INF);
            if(now>=sum) break;
        }
        for(int t=0;t<=mid;t++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++) id[t][i][j]=0;
        return now>=sum;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++) scanf("%s",mp[i]+1);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++) sum+=(mp[i][j]=='.');
        pre();
        int L=0,R=n*m,mid,ans=M;
        while(L<=R)
        {
            mid=L+R>>1;
            if(check(mid)) R=mid-1,ans=mid;
            else L=mid+1;
        }
        if(ans==M) printf("impossible
    ");
        else printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    《网络》:关于计算机网络的必备常识【无序】(不定时更新)
    《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet
    《网络》:交换机基本配置命令
    启动eclipse时出现“Failed to load the JNI shared library jvm.dll”错误及解决
    java之servlet小记
    Nokia大事录
    Android之HandlerThread
    Android进程间的通信之AIDL
    Android进程间的通信之Messenger
    Loaders
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11381049.html
Copyright © 2020-2023  润新知