Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3831  Solved: 1119
[Submit][Status][Discuss]

Description

发生了火警,所有人员需要紧急疏散!假设每个房间是一个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

这题网络流真恶心。。。

二分+最大流

由源点S连向每个空地,容量为1

二分时间time,将每个门拆成time个点,从门bfs到空地(人),如果从空地到门能在x的时间内到达,则将空地连向第x扇门

每扇门连向汇点,容量为1,表示单位时间内只能出去一个人

然后每扇门向下一扇门连线,容量为INF,表示多出来的人等下一扇门

PS:网上大多数题解有错误

4 5
XXXDX
XXX.X
X.X.D
.....

ans=6

大部分题解没有考虑门在单位时间内只能出一人

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std; #define ID(i,j) (i*m+j)
const int INF=0x7f7f7f7f;
const int MAXN=;
const int xx[]={-,,,};
const int yy[]={,,-,}; struct Edge
{
int to,w,next;
}E[MAXN];
int node=,head[MAXN],dis[MAXN];
int s=,t=1e5+;
int n,m,ans,sum; int mp[][]; void insert(int u,int v,int w)
{
E[++node]=(Edge){v,w,head[u]};
head[u]=node;
E[++node]=(Edge){u,,head[v]};
head[v]=node;
} bool bfs()
{
memset(dis,-,sizeof(dis));
queue<int> Q;
Q.push(s);
dis[s]=;
while(!Q.empty())
{
int q=Q.front();Q.pop();
for(int i=head[q];i;i=E[i].next)
if(E[i].w&&dis[E[i].to]==-)
{
Q.push(E[i].to);
dis[E[i].to]=dis[q]+;
}
}
return dis[t]!=-;
} int dfs(int x,int flow)
{
if(x==t) return flow;
int w,used=;
for(int i=head[x];i;i=E[i].next)
if(E[i].w&&dis[E[i].to]==dis[x]+)
{
w=flow-used;
w=dfs(E[i].to,min(w,E[i].w));
E[i].w-=w;
E[i^].w+=w;
used+=w;
if(used==flow)return flow;
}
if(!used) dis[x]=-;
return used;
} void dinic()
{
while(bfs()) ans+=dfs(s,INF);
} struct NODE
{
int x,y,t;
};
int cnt=; void bfs(NODE N,int time)
{
bool vis[][];
queue<NODE> Q;
memset(vis,,sizeof(vis));
for(int i=;i<;i++)
{
int x=N.x+xx[i],y=N.y+yy[i];
if(!vis[x][y])
{
Q.push((NODE){x,y,});
vis[x][y]=;
}
}
while(!Q.empty())
{
NODE T=Q.front();Q.pop();
if(T.x<||T.x>n||T.y<||T.y>m) continue;
if(T.t>time) continue;
if(mp[T.x][T.y]!=) continue;
for(int i=;i<;i++)
{
int x=T.x+xx[i],y=T.y+yy[i];
if(!vis[x][y])
{
Q.push((NODE){x,y,T.t+});
vis[x][y]=;
}
}
insert(ID(T.x,T.y),cnt*+T.t,);
}
} bool check(int x)
{
cnt=;
node=;ans=;
memset(head,,sizeof(head));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
if(mp[i][j]==) insert(s,ID(i,j),);
else if(mp[i][j]==-)
{
cnt++;
insert(cnt*+,t,);
for(int k=;k<=x;k++)
{
insert(cnt*+k,t,);
insert(cnt*+k-,cnt*+k,INF);
}
bfs((NODE){i,j,},x);
}
dinic();
if(ans==sum) return true;
return false;
} int main()
{
char ch[];
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",ch+);
for(int j=;j<=m;j++)
if(ch[j]=='.') sum++;
else if(ch[j]=='X') mp[i][j]=;
else if(ch[j]=='D') mp[i][j]=-;
}
int left=,right=n*m;
while(left<right)
{
int mid=(left+right)>>;
if(check(mid)) right=mid;
else left=mid+;
}
if(right==n*m) printf("impossible");
else printf("%d",right);
return ;
}

1189: [HNOI2007]紧急疏散evacuate的更多相关文章

  1. BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )

    我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...

  2. bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流

    [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3626  Solved: 1059[Submit][St ...

  3. 【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1189 表示完全不会QAQ.... 于是膜拜题解orz 二分时间........... 于是转换成判定 ...

  4. BZOJ 1189 [HNOI2007]紧急疏散evacuate

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...

  5. 1189: [HNOI2007]紧急疏散evacuate - BZOJ

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...

  6. bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分

    Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...

  7. Bzoj1189 [HNOI2007]紧急疏散evacuate

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2293  Solved: 715 Descr ...

  8. BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流

    1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1132  Solved: 412[Submi ...

  9. bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate

    http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...

随机推荐

  1. xftp的使用教程

    使用xftp来上传,下载文件到linux主机 首先,我们要下载一个xftp,因为官网是英文的,还需要邮件激活,在这里我把程序下载好 此时已经安装完成,点击finish,打开软件登录SSH账号,这里以默 ...

  2. python文件操作和集合(三)

    对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 文件基本操作:         f = open('file.txt','r') #以 ...

  3. Spring核心-IOC-AOP-模版

    1. POM- 1.1 中央仓库 1.2 各包作用 spring-core.jar 核心工具类 spring-beans.jar 是所有应用都要用到的,它包含访问配置文件.创建和管理bean 以及进行 ...

  4. HDU 4355——Party All the Time——————【三分求最小和】

    Party All the Time Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  5. netty之==TCP粘包/拆包问题解决之道(一)

    一.TCP粘包/拆包是什么 TCP是一个“流”协议,所谓流,就是没有界限的一长串二进制数据.TCP作为传输层协议并不不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行数据包的划分,所以在 ...

  6. genymotion安装及使用出现的问题

    此处总结genymotion出现的问题. 1)安装好genymotion后,新建一个模拟器.去下载的时候报错 Unable to create Virtual Device: Connection t ...

  7. 第一个flask程序

    flask简介: flask是一款非常流行的Python Web框架,出生于2010年,作者是Armin  Ronacher,本来这个项目只是作者在愚人节的一个玩笑,后来由于非常受欢迎,进而成为一个正 ...

  8. python 3.6 链接mssql 进行数据操作

    #!/usr/bin/env python # -*- coding: UTF-8 -*- import pymssql class MSSQL(object): ''' 对pymssql的简单封装 ...

  9. MySQL(五)

    一.视图 视图是一个虚拟表(非真实存在),其本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用名称即可获取结果集,可以将该结果集当做表来使用. 使用视图我们可以把查询过程中的临时表摘 ...

  10. (三)JavaScript之[事件]与[字符串]

    5].事件**JavaScript事件:HTML事件 * HTML事件是发生在HTML元素上的事情 * HTML事件可以是[浏览器的行为],也可以是[用户的行为] * * 实例: * HTML页面完成 ...