• HNOI2007 紧急疏散


    题目链接:戳我

    我们可以先用最短路BFS预处理出来每个空地到门的距离,然后建图。
    因为每个单位时间每个门只能通过1个人,所以我们还要给门按时间拆点。
    但是我们不知道这个时间.....所以还要二分时间。
    显然时间越长,方案越容易是合法的,时间越短,越不容易存在全部疏散的方案。

    然后思路就清晰了。我们二分这个时间x,从S到每个出发点都连接一条容量为的1的边。然后对于每个点,如果它到某个门所需要的时间小于x,我们就向表示那个时间的门的点连接一条容量为1的边。然后因为每个时间每个门都最多只能出来一个人,所以我们给每个时间的每个门的点向T连容量为1的边。然后因为到了门之后等待,让别人先过,所以每个门都要向它自己的下一个时间的点连一条容量为INF的边。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #define MAXN 100010
    #define INF 0x3f3f3f3f
    using namespace std;
    int n,m,t,S,T,tot,cnt1,cnt2;
    int id[100][100],X[MAXN],Y[MAXN],tt[MAXN];
    int head[MAXN],done[100][100],dis[2000][2000],dep[MAXN],cur[MAXN];
    int move_x[4]={0,0,1,-1},move_y[4]={1,-1,0,0};
    char a[100][100];
    struct Edge{int nxt,to,dis;}edge[200010];
    inline void add(int from,int to,int dis)
    {
        // printf("[%d %d] %d
    ",from,to,dis);
        edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=0,head[to]=t;
    }
    inline bool bfs()
    {
        memset(dep,0x3f,sizeof(dep));
        memcpy(cur,head,sizeof(head));
        queue<int>q;
        q.push(S);
        dep[S]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dep[v]==0x3f3f3f3f&&edge[i].dis)
                {
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
        if(dep[T]==0x3f3f3f3f) return false;
        return true;
    }
    inline int dfs(int x,int f)
    {
        if(x==T||!f) return f;
        int used=0,w;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            if(dep[edge[i].to]==dep[x]+1&&(w=dfs(edge[i].to,min(f,edge[i].dis))))
            {
                used+=w,f-=w;
                edge[i].dis-=w,edge[i^1].dis+=w;
                if(!f) break;
            }
        }
    
        return used;
    }
    inline int dinic()
    {
        int cur_ans=0;
        while(bfs()) cur_ans+=dfs(S,(int)1e9);
        return cur_ans;
    }
    inline void init(int K,int x,int y)
    {
        memset(done,0,sizeof(done));
        queue<int>qx,qy;
        memset(dis[K],0x3f,sizeof(dis[K]));
        qx.push(x),qy.push(y);
        done[x][y]=1;
        dis[K][id[x][y]]=0;
        while(!qx.empty())
        {
            int u=qx.front(),v=qy.front();
            qx.pop(),qy.pop();
            for(int i=0;i<4;i++)
            {
                int xx=u+move_x[i],yy=v+move_y[i];
                if(done[xx][yy]) continue;
                done[xx][yy]=1;
                if(xx<1||xx>n||yy<1||yy>m||a[xx][yy]!='.') continue;
                dis[K][id[xx][yy]]=dis[K][id[u][v]]+1;
                qx.push(xx),qy.push(yy);
            }
        }
    }
    inline bool check(int x)
    {
        memset(head,0,sizeof(head));
        t=1,S=0,T=50000;
        int kkk=n*m;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(a[i][j]=='.')
                    add(S,id[i][j],1);
        for(int i=1;i<=cnt2;i++)
        {
            for(int j=1;j<=x;j++) tt[j]=++kkk;
            for(int j=1;j<x;j++) add(tt[j],tt[j+1],INF);
            for(int j=1;j<=x;j++) add(tt[j],T,1);
            for(int p=1;p<=n;p++)
                for(int q=1;q<=m;q++)
                    if(a[p][q]=='.'&&dis[i][id[p][q]]<=x)
                        add(id[p][q],tt[dis[i][id[p][q]]],1);
        }
        int cur_ans=dinic();
        if(cur_ans==cnt1) return true;
        else return false;
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                cin>>a[i][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                id[i][j]=++tot;
                if(a[i][j]=='.') ++cnt1;
                if(a[i][j]=='D') ++cnt2,X[cnt2]=i,Y[cnt2]=j;
            }
        for(int i=1;i<=cnt2;i++) init(i,X[i],Y[i]);
        int l=0,r=2000,ans=-1;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            // printf("l=%d r=%d mid=%d
    ",l,r,mid);
            if(check(mid)==true) ans=mid,r=mid-1;
            else l=mid+1;
        }
        if(ans==-1) printf("impossible
    ");
        else printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    OpenCv 人脸识别 基础
    C++ 0x std::async 的应用
    C++ 0x 使用condition_variable 与 Mutex 同步两个线程
    Unity C# 调用 C++ DLL 并在 DLL 中调用 C# 的回调函数
    C++ 11 中的 Lambda 表达式的使用
    DirectShow 制作在Unity3D中可以设置进度的视频播放插件
    Async/Await 如何通过同步的方式实现异步
    React Native 开源项目汇总
    ES6 Promise的理解与简单实现(链接)
    深刻理解BFC(链接)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10856970.html
Copyright © 2020-2023  润新知