题目传送门

思路:

  先预处理出每个人到每扇门的时间,用门作为起点进行bfs处理。

  然后二分时间,假设时间为x,将每扇门拆成1到x,x个时间点,表示这扇门有几个时间点是可以出去的。对于一扇门,每个时间点都向后一个时间点建边,表示人在当前时间点到达,可以在下一时间点出去。

  先将s连上所有的空地,流量为1,建立每个空地每个门的对应的时间点流量为1的边,表示这个空地的人会再某一时间点到达这扇门。然后每个门流向t,流量为inf。只要最大流为空地的数量,则代表该时间是可以的,继续向下二分。

#include<bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int fx[][]={{,},{,-},{,},{-,}};
int dis[][][],n,m;
char s[][];
int ed[],g[][],cnt,sum,st,t;
const int maxn=;
const int inf=0x3f3f3f3f;
int head[maxn],tot=;
struct edge{
int to,f,Next;
}a[maxn<<];
void addv(int u,int v,int w){
a[++tot].to=v,a[tot].f=w,a[tot].Next=head[u],head[u]=tot;
a[++tot].to=u,a[tot].f=,a[tot].Next=head[v],head[v]=tot;
}
inline void bfs(int id){
queue<int >q;
dis[id][ed[id]/m][ed[id]%m]=;
q.push(ed[id]);
while(!q.empty()){
int u=q.front();
int x=u/m,y=u%m;
q.pop();
for(int i=;i<;i++){
int xx=x+fx[i][],yy=y+fx[i][];
if(xx<||xx>=n||yy<||yy>=m||s[xx][yy]!='.')continue;
if (dis[id][xx][yy]>dis[id][x][y]+)
dis[id][xx][yy]=dis[id][x][y]+,q.push(xx*m+yy); }
}
}
int deep[maxn];
bool vis[maxn];
inline void find(){
CLR(deep,);
queue<int >q;
vis[st]=;
q.push(st);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head[u];i!=-;i=a[i].Next)
{
if(a[i].f && !vis[a[i].to]){
q.push(a[i].to);
deep[a[i].to]=deep[u]+;
vis[a[i].to]=;
}
}
}
}
int dfs(int u,int delta){
if(u==t)return delta;
int ret=;
for(int i=head[u];delta&&i!=-;i=a[i].Next){
if(a[i].f&&deep[a[i].to]==deep[u]+){
int dd=dfs(a[i].to,min(a[i].f,delta));
a[i].f-=dd;
a[i^].f+=dd;
delta-=dd;
ret+=dd;
}
}
return ret;
}
inline bool check(int x){
st=,t=maxn-,tot=;
CLR(head,-);
for(int i=;i<=sum;i++)addv(st,i,);
for(int k=;k<=cnt;k++)
for(int i=;i<n;i++)
for(int j=;j<m;j++)
if(s[i][j]=='.'&&dis[k][i][j]<=x)
addv(g[i][j],sum+(k-)*x+dis[k][i][j],); for (int i=; i<=cnt; i++)
for (int j=; j<=x; j++) {
int tmp=(i-)*x+sum;
addv(tmp+j,t,);
if (j<x) addv(tmp+j,tmp+j+,inf);
}
int ret=;
while(){
CLR(vis,);
find();
if(!vis[t]){
return ret==sum;
}
ret+=dfs(st,inf);
}
}
int main(){
cin>>n>>m;
for(int i=;i<n;i++)
{
scanf("%s",s[i]);
}
for(int i=;i<n;i++)
{
for(int j=;j<m;j++)
{
if(s[i][j]=='D'){
ed[++cnt]=i*m+j;
}
if(s[i][j]=='.')g[i][j]=++sum;
}
}
CLR(dis,0x3f);
for(int i=;i<=cnt;i++)
{
bfs(i);
}
int l=,r=n*m,mid;
int ans;
if(!check(r)){
puts("impossible");
return ;
}
while(l<=r){ mid=(l+r)>>;//printf("l:%d r:%d mid:%d\n",l,r,mid);
if(check(mid)){
ans=mid,r=mid-;
// printf("ans:%d\n",ans);
}
else l=mid+;
}
cout<<ans<<endl; }

1189: [HNOI2007]紧急疏散evacuate

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 3825  Solved: 1118
[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

bzoj 1189 二分+最大流的更多相关文章

  1. bzoj 1189 二分+最大流判定

    首先我们可以二分一个答案时间T,这样就将最优性问题 转化为了判定性问题.下面我们考虑对于已知的T的判定 对于矩阵中所有的空点bfs一次,得出来每个点到门的距离, 然后连接空点和每个能在t时间内到达的门 ...

  2. BZOJ 1189 二分匹配 || 最大流

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

  3. bzoj 1305 二分+最大流判定|贪心

    首先我们二分一个答案mid,在判定是否能举办mid次,那么对于每个次我们可以用最大流根据是否满流(流量为n*mid)来判定,对于每个点我们拆成两个点,分别表示这个人要和他喜欢和不喜欢的人一起跳舞,那么 ...

  4. uvalive 3231 Fair Share 公平分配问题 二分+最大流 右边最多流量的结点流量尽量少。

    /** 题目: uvalive 3231 Fair Share 公平分配问题 链接:https://vjudge.net/problem/UVALive-3231 题意:有m个任务,n个处理器,每个任 ...

  5. poj 2391 Ombrophobic Bovines 最短路 二分 最大流 拆点

    题目链接 题意 有\(n\)个牛棚,每个牛棚初始有\(a_i\)头牛,最后能容纳\(b_i\)头牛.有\(m\)条道路,边权为走这段路所需花费的时间.问最少需要多少时间能让所有的牛都有牛棚可待? 思路 ...

  6. HDU3081 Marriage Match II —— 传递闭包 + 二分图最大匹配 or 传递闭包 + 二分 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3081 Marriage Match II Time Limit: 2000/1000 MS (Java/Others)    ...

  7. HDU-3081-Marriage Match II 二分图匹配+并查集 OR 二分+最大流

    二分+最大流: 1 //题目大意:有编号为1~n的女生和1~n的男生配对 2 // 3 //首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 4 // 5 //然后输入f组,c,d表示 ...

  8. hdu4560 不错的建图,二分最大流

    题意: 我是歌手 Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others) Total Subm ...

  9. POJ3228二分最大流

    题意:       有n个点,每个点有两个权值,金子数量还有仓库容量,金子可以存在自己的仓库里或者是别的仓库里,仓库和仓库之间有距离,问所有金子都必须存到库里最大距离的最小是多少? 思路:       ...

随机推荐

  1. python3-递归

    # Auther: Aaron Fan """递归特性:1. 必须有一个明确的结束条件2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少3. 递归效率不高,递 ...

  2. 专题2-通过按键玩中断\第1课-中断处理流程深度剖析-lesson1

    中断概念 1.中断生命周期 串口先产生一个事件,该事件传送到中断控制器里面,中断控制器会进行相应过滤,能通过过滤,那么就交给CPU去处理. 2.中断源 2440芯片手册 6410芯片手册 3.中断过滤 ...

  3. Responsive设计——meta标签

    media-queries.js(http://code.google.com/p/css3-mediaqueries-js/) respond.js(https://github.com/scott ...

  4. javascript总结1:js常见页面消息输出方式 alert confirm console prompt document

    .1 js常见的输出方法: 1-1 alert 警告框 alert("js语法总结"); 1-2 confirm 确认方法 confirm("js语法总结"); ...

  5. C#序列化xml,开发常用

    序列化操作对于开发人员来说最熟悉不过了. 序列化分为:序列化和反序列化. 序列化名词解释:序列化是将对象状态转换为可保持或传输的格式的过程. 与序列化相对的是反序列化,它将流转换为对象.这两个过程结合 ...

  6. SQL聚集索引和非聚集索引的区别

    其实对于非专业的数据库操作人员来讲,例如软件开发人员,在很大程度上都搞不清楚数据库索引的一些基本知识,有些是知其一不知其二,或者是知其然不知其所以然.造成这种情况的主要原因我觉的是行业原因,有很多公司 ...

  7. POJ-3481 Double Queue (splay)

    The new founded Balkan Investment Group Bank (BIG-Bank) opened a new office in Bucharest, equipped w ...

  8. aspx 与 ashx cs

    1. aspx 与 ashx 我们知道 aspx :继承自 System.Web.UI.Page 然而Page:IHttpHandler public class Page : TemplateCon ...

  9. C# 类型初始化(Type initialization)

    这些天突然看到一些大虾门写的有关类型初始化的文章.那种感觉真叫跌宕起伏啊. 博文地址如下,自己慢慢体会吧! 起步:http://www.cnblogs.com/artech/archive/2008/ ...

  10. URLRewrite 实现方法详解

    所谓的伪静态页面,就是指的URL重写,在ASP.NET中实现非常简单首先你要在你的项目里引用两个DLL:ActionlessForm.dll.URLRewriter.dll,真正实现重写的是 URLR ...