BZOJ 1189([HNOI2007]紧急疏散evacuate-网络流二分+拆点)
2017-01-31 11:50
471 查看
发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是’.’,那么表示这是一块空地;如果是’X’,那么表示这是一面墙,如果是’D’,那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。
Input
输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符’.’、’X’和’D’,且字符间无空格。
Output
只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出’impossible’(不包括引号)。
Sample Input
5 5
XXXXX
X…D
XX.XX
X..XX
XXDXX
Sample Output
3
HINT
2015.1.12新加数据一组,鸣谢1756500824
C++语言请用scanf(“%s”,s)读入!
BFS计算出每个人离每个出口的距离,网络流,二分+拆点,注意一个人不能路过一个出口到达另一个出口(因为出口格子有人数限制)d。
Input
输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符’.’、’X’和’D’,且字符间无空格。
Output
只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出’impossible’(不包括引号)。
Sample Input
5 5
XXXXX
X…D
XX.XX
X..XX
XXDXX
Sample Output
3
HINT
2015.1.12新加数据一组,鸣谢1756500824
C++语言请用scanf(“%s”,s)读入!
BFS计算出每个人离每个出口的距离,网络流,二分+拆点,注意一个人不能路过一个出口到达另一个出口(因为出口格子有人数限制)d。
#include<cstdio> #include<queue> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=Pre[x];p;p=Next[p]) #define Forpiter(x) for(int &p=iter[x];p;p=Next[p]) #define pi pair<int,int> #define pb push_back #define mp make_pair #define fi first #define se second #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (400+400*800+100) #define MAXM (6000000+100) #define PRi2D(a,n,m) For(i,n) { \ For(j,m-1) cout<<a[i][j]<<' ';\ cout<<a[i][m]<<endl; \ } long long mul(long long a,long long b){return (a*b)%F;} long long add(long long a,long long b){return (a+b)%F;} long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} typedef long long ll; int read() { int x=0,f=1; char ch=getchar(); while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();} return x*f; } class Max_flow //dinic+µ±Ç°»¡ÓÅ»¯ { public: int n,t; int q[MAXN]; int edge[MAXM],Next[MAXM],Pre[MAXN],weight[MAXM],size; void addedge(int u,int v,int w) { edge[++size]=v; weight[size]=w; Next[size]=Pre[u]; Pre[u]=size; } void addedge2(int u,int v,int w){addedge(u,v,w),addedge(v,u,0);} bool b[MAXN]; int d[MAXN]; bool SPFA(int s,int t) { For(i,n) d[i]=INF; MEM(b) d[q[1]=s]=0;b[s]=1; int head=1,tail=1; while (head<=tail) { int now=q[head++]; Forp(now) { int &v=edge[p]; if (weight[p]&&!b[v]) { d[v]=d[now]+1; b[v]=1,q[++tail]=v; } } } return b[t]; } int iter[MAXN]; int dfs(int x,int f) { if (x==t) return f; Forpiter(x) { int v=edge[p]; if (weight[p]&&d[x]<d[v]) { int nowflow=dfs(v,min(weight[p],f)); if (nowflow) { weight[p]-=nowflow; weight[p^1]+=nowflow; return nowflow; } } } return 0; } int max_flow(int s,int t) { (*this).t=t; int flow=0; while(SPFA(s,t)) { For(i,n) iter[i]=Pre[i]; int f; while (f=dfs(s,INF)) flow+=f; } return flow; } void mem(int n) { (*this).n=n; size=1; MEM(Pre) } }S; #undef MAXN #define MAXN (30) char s[MAXN][MAXN]; int h[MAXN][MAXN]={0}; const int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}}; int dis[450][450]; int n,m; bool inside(int i,int j) {return 1<=i&&i<=n&&1<=j&&j<=m&&s[i][j]!='X'; } int id(int i,int j){return i*m-m+j;} void bfs(int i,int j) { int st=id(i,j); dis[st][st]=0; queue < pi > q; q.push(mp(i,j)); while(!q.empty()) { pi now=q.front(); q.pop(); int x=now.fi,y=now.se; Rep(di,4) { int nx=x+dir[di][0],ny=y+dir[di][1]; if (inside(nx,ny)&&dis[st][id(nx,ny)]==INF) { dis[st][id(nx,ny)]=dis[st][id(x,y)]+1; if (s[nx][ny]!='D') q.push(mp(nx,ny)); } } } } #define vi vector<int> #define SI(x) ((x).size()) vi v1,v2; int sz1,sz2; void prework() { For(i,n) For(j,m) if (s[i][j]=='.') v1.pb(id(i,j)); else if (s[i][j]=='D') v2.pb(id(i,j)); sz1=SI(v1);sz2=SI(v2); } int check(int t) { S.mem(sz1+sz2*t+2); int tot2=sz1+sz2*t,st=tot2+1,ed=st+1; For(i,sz1) S.addedge2(st,i,1); Fork(i,sz1+1,tot2) S.addedge2(i,ed,1); For(i,sz1) For(j,sz2) if (dis[v1[i-1]][v2[j-1]]<=t) { S.addedge2(i,sz1+t*(j-1)+dis[v1[i-1]][v2[j-1]],1); } For(i,sz2) { For(d,t-1) { S.addedge2(sz1+t*(i-1)+d,sz1+t*(i-1)+d+1,sz1); } } int ans=S.max_flow(st,ed); return ans; } int main() { // freopen("bzoj1189.in","r",stdin); // freopen(".out","w",stdout); cin>>n>>m; For(i,n) scanf("%s",s[i]+1); int p=0; For(i,n) For(j,m) if (s[i][j]=='D') { h[i][j]=++p; } int cnt=0; MEMI(dis) For(i,n) For(j,m) if (s[i][j]=='.') { ++cnt,bfs(i,j); } int l=0,r=2*n*m,ans=INF; prework(); while(l<=r) { int m=l+r>>1; if (check(m)==cnt) ans=m,r=m-1;else l=m+1; } if (ans==INF) puts("impossible"); else printf("%d\n",ans); return 0; }
相关文章推荐
- 网络协议理论
- quagga源码学习--BGP协议对等体连接tcp md5签名认证选项
- 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。
- AJAX-XMLHttpRequest和本地文件
- 【tcpdump】数据抓包
- WLAN 无线网络 04 - RF 测量与数学原理
- WLAN 无线网络 03 - RF 基础
- Delphi xe5 控件TIdhttp的用法post,get解决中文乱码问题
- 神经网络学习笔记-02-循环神经网络
- 通俗理解卷积神经网络
- C++ 不用std::queue 实现读取网络字节缓冲去的队列
- 飞行员配对方案问题 洛谷2756 网络流
- 简析TCP的三次握手与四次分手
- TCP连接为什么三次握手和四次挥手
- ubuntu16.04能连接wifi但是没有网络
- 架构师养成记--20.netty的tcp拆包粘包问题
- 增强学习系列之(三):实现一个打砖块的游戏
- 链路层:SLIP、PPP、ARP、RARP
- Maven项目下HttpServletRequest 或 HttpServletResponse需引用的依赖包
- HTTP 协议详解