luogu P3191 [HNOI2007]緊急疏散EVACUATE
阿新 • • 發佈:2018-11-06
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\n",ans):puts("impossible"); return 0; }