• luogu P3191 [HNOI2007]紧急疏散EVACUATE


    传送门

    qwq这题好大力

    首先可以预处理出每个人到每个门前面那个格子的最早时间,然后答案如果比最小答案大的话也是合法的,所以可以二分最终答案.检查(mid)是否合法就考虑每个人要去哪个门才会合法,所以可以网络流:从原点向每个人连容量为1的边;对所有门建(mid)个点,每个点都向汇点连容量为(1)的边,并且向下一个时间的点连(inf)边,表示每个门每个时刻最多走1个人,同时剩下的人可以在后面的时刻出去;每个人向每个门在最早能到的时间对应的点连1边,然后(dinic)判断是否流量等于人数即可

    ps:本人网络流板子极丑,慎看

    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define eps (1e-5)
    
    using namespace std;
    const int N=22,M=N*N*N*N*2,P=N*N*N,inf=2333333;
    il LL rd()
    {
      LL x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int to[M],nt[M],w[M],hd[P],tot=1;
    il void add(int x,int y,int z)
    {
      ++tot,to[tot]=y,nt[tot]=hd[x],w[tot]=z,hd[x]=tot;
      ++tot,to[tot]=x,nt[tot]=hd[y],w[tot]=0,hd[y]=tot;
    }
    int lv[P],ss,tt;
    bool iqu[P];
    bool bfs()
    {
      memset(lv,63,sizeof(lv));
      memset(iqu,0,sizeof(iqu));
      lv[ss]=1,iqu[ss]=true;
      queue<int> q;
      q.push(ss);
      while(!q.empty())
        {
          int x=q.front();
          q.pop();
          for(int i=hd[x];i;i=nt[i])
            {
              int y=to[i],c=w[i];
              if(c>0&&lv[y]>lv[x]+1)
                {
                  lv[y]=lv[x]+1;
                  if(!iqu[y]) q.push(y);
                  iqu[y]=true;
                }
            }
          iqu[x]=false;
        }
      return lv[tt]<lv[tt+1];
    }
    int dfs(int x,int nw)
    {
      if(x==tt) return nw;
      int sm=0;
      for(int i=hd[x];i&&nw;i=nt[i])
        {
          int y=to[i],c=w[i];
          if(c>0&&lv[y]==lv[x]+1)
            {
              int dt=dfs(y,min(nw,c));
              w[i]-=dt,w[i^1]+=dt;
              sm+=dt,nw-=dt;
            }
        }
      return sm;
    }
    int mvx[4]={0,1,0,-1},mvy[4]={1,0,-1,0};
    int n,m,a[N][N],pp[N*N][2],tp,dr[N*N][2],td,di[N][N],ed[N*N][N*N];
    bool v[N][N];
    il bool check(int mid)
    {
      tt=tp+(mid+1)*td+3;
      memset(hd,0,sizeof(hd)),tot=1;
      for(int j=1;j<=td;j++)
        for(int i=0;i<mid;i++) add(j+tp+i*td,tt,1),add(j+tp+i*td,j+tp+(i+1)*td,inf);
      for(int i=1;i<=tp;i++)
        {
          add(ss,i,1);
          for(int j=1;j<=td;j++) if(ed[i][j]<mid) add(i,j+tp+ed[i][j]*td,1);
        }
      int sm=0;
      while(bfs())
        sm+=dfs(ss,inf);
      return sm==tp;
    }
    
    int main()
    {
      n=rd(),m=rd();
      char cc[N];
      for(int i=1;i<=n;i++)
        {
          scanf("%s",cc+1);
          for(int j=1;j<=m;j++)
            {
              if(cc[j]=='.') pp[++tp][0]=i,pp[tp][1]=j,a[i][j]=1;
              else if(cc[j]=='D') dr[++td][0]=i,dr[td][1]=j,a[i][j]=1;
            }
        }
      memset(ed,63,sizeof(ed));
      queue<int> q1,q2;
      for(int h=1;h<=tp;h++)
        {
          int sx=pp[h][0],sy=pp[h][1];
          memset(di,63,sizeof(di));
          di[sx][sy]=0,v[sx][sy]=true;
          q1.push(sx),q2.push(sy);
          while(!q1.empty())
            {
              int x=q1.front(),y=q2.front();
              q1.pop(),q2.pop();
              for(int i=0;i<4;i++)
                {
                  int xx=x+mvx[i],yy=y+mvy[i];
                  if(a[xx][yy]&&di[xx][yy]>di[x][y]+1)
                    {
                      di[xx][yy]=di[x][y]+1;
                      if(!v[xx][yy]) q1.push(xx),q2.push(yy);
                    }
                }
              v[x][y]=false;
            }
          for(int o=1;o<=td;o++) ed[h][o]=di[dr[o][0]][dr[o][1]]-1;
        }
      int l=1,r=n*m,ans=-1;
      while(l<=r)
        {
          int mid=(l+r)>>1;
          if(check(mid)) ans=mid,r=mid-1;
          else l=mid+1;
        }
      ans>0?printf("%d
    ",ans):puts("impossible");
      return 0;
    }
    
    
    
  • 相关阅读:
    LeetCode-160. Intersection of Two Linked Lists
    LeetCode-328. Odd Even Linked List
    LeetCode-234. Palindrome Linked List
    Trie树
    圆圈中最后剩下的数字
    LeetCode-215. Kth Largest Element in an Array
    n个骰子的和
    DFS & BFS
    ubuntu14.04安装显卡驱动(转载)
    Ubuntu 14.04 配置caffe环境
  • 原文地址:https://www.cnblogs.com/smyjr/p/9917888.html
Copyright © 2020-2023  润新知