发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是‘.‘,那么表示这是一块空地;如果是‘X‘,那么表示这是一面墙,如果是‘D‘,那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。
输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符‘.‘、‘X‘和‘D‘,且字符间无空格。
只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出‘impossible‘(不包括引号)。
5 5 XXXXX X...D XX.XX X..XX XXDXX
3
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// #define inf 0x3f3f3f3f const int N=1e2+44; const int M=1e6+54; int d[N]; struct edge { int to, next, w; } e[M << 1]; int head[M],cur[M],cnt = 1; void add(int x, int y, int z) { e[++cnt] = (edge){y, head[x], z}; head[x] = cnt; e[++cnt] = (edge){x, head[y], 0}; head[y] = cnt; } void init() { cnt=1;CLR(head,0);CLR(cur,0); } void ins(int x,int y,int a,int b) { add(x,y,b-a); d[x]-=a; d[y]+=a; } int level[M]; bool bfs(int s, int t) { memset(level, 0, sizeof level); queue<int> q; level[s] = 1; q.push(s); while (!q.empty()) { int pos = q.front();q.pop(); for (int i = head[pos]; i; i = e[i].next) { int nx = e[i].to; if (!e[i].w || level[nx]) continue; level[nx] = level[pos] + 1; q.push(nx); } } return level[t]; } int dfs(int s, int t, int flow) { if(s==t||flow==0)return flow; int f,ret = 0; for (int &i = cur[s],v; i; i = e[i].next) { v = e[i].to; if (level[v] == level[s] + 1 && (f=dfs(v,t,min(flow,e[i].w)))>0) { e[i].w -= f; e[i ^ 1].w += f; flow -= f; ret += f; if(!flow)break; } } return ret; } int dinic(int s, int t) { int ret = 0; while (bfs(s, t)) memcpy(cur,head,sizeof cur),ret += dfs(s, t, inf); return ret; } int n,m,s,t,a,b,c,sum,S,T,k; char mp[100][100],id[100][100],pos,posdoor; int dx[]={1,0,-1,0}; int dy[]={0,-1,0,1}; vector<pair<int,int> >door,peo[400+4]; struct node { int x,y,d; }u,v; queue<node>q; int vis[100][100]; bool check(int mid) { init(); rep(i,1,pos) { add(s,i,1); for(int j=0;j<peo[i].size();j++) { if(peo[i][j].second<=mid) add(i,pos+2+mid*(peo[i][j].first)+peo[i][j].second,1); } } rep(i,1,posdoor) { rep(j,1,mid) { add( (i)*mid+j+pos+2,t,1); if(j!=mid)add( (i)*mid+j+pos+2,(i)*mid+j+pos+3,inf); } } return dinic(s,t)==pos; } int main() { scanf("%d%d",&n,&m); rep(i,1,n)scanf("%s",mp[i]+1); rep(i,1,n) rep(j,1,m) if(mp[i][j]==‘D‘) door.push_back(make_pair(i,j)); else if(mp[i][j]==‘.‘) id[i][j]=++pos; s=pos+1,t=s+1; posdoor=door.size(); for(int i=0;i<door.size();i++) { CLR(vis,0); while(!q.empty())q.pop(); u.x=door[i].first; u.y=door[i].second; u.d=0;vis[u.x][u.y]=1; q.push(u);int xx,yy; while(!q.empty()) { u=q.front();q.pop(); rep(j,0,3) { v.x=u.x+dx[j]; v.y=u.y+dy[j]; v.d=u.d+1; if(v.x>=1&&v.x<=n&&v.y>=1&&v.y<=m&&!vis[v.x][v.y]&&mp[v.x][v.y]==‘.‘) { peo[id[v.x][v.y]].push_back(make_pair(i+1,v.d)); vis[v.x][v.y]=1; q.push(v); } } } } int ans=-1,R=1000,L=1; while(L<=R) { int mid=(L+R)>>1; if(check(mid))R=mid-1,ans=mid; else L=mid+1; } if(ans==-1)printf("impossible\n"); else printf("%d\n",ans); return 0; }
P3191 [HNOI2007]紧急疏散EVACUATE 最大流 二分
原文:https://www.cnblogs.com/bxd123/p/11314152.html