求出所有人撤离的最短时间。由于每扇门只能通过一次,所以不能简单用bfs来搞。

显然答案是有单调性的,考虑二分,问题变成了判断时间x所有人能不能撤离。

考虑最大流。对于每扇门,每个时间通过的人数最多为1,所以将每扇门按时间x来拆成x个点。连边(time/i,1,t)来限制流量。

另外对于每个人m,如果能在时间t到达门d,那么连边(m,d/t,1)。再把源点和所有人连一条容量为1的边。

则可以通过判断最大流是否满流来得出所有人能不能撤离。

由于(n,m)<=20.所以可以很轻松的跑出答案。

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... char ss[N][N];
struct Node{int vis[N][N];}node[N*N];
int pos, num, n, m, ps[][]={,,,-,,,-,};
queue<int>Q;
queue<PII>que;
struct Edge{int p, next, w;}edge[];
int head[], cnt=, s, t, vis[]; void add_edge(int u, int v, int w){
edge[cnt].p=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;
edge[cnt].p=u; edge[cnt].w=; edge[cnt].next=head[v]; head[v]=cnt++;
}
int bfs(){
int i, v;
mem(vis,-);
vis[s]=; Q.push(s);
while (!Q.empty()) {
v=Q.front(); Q.pop();
for (i=head[v]; i; i=edge[i].next) {
if (edge[i].w> && vis[edge[i].p]==-) {
vis[edge[i].p]=vis[v] + ;
Q.push(edge[i].p);
}
}
}
return vis[t]!=-;
}
int dfs(int x, int low){
int i, a, temp=low;
if (x==t) return low;
for (i=head[x]; i; i=edge[i].next) {
if (edge[i].w> && vis[edge[i].p]==vis[x]+){
a=dfs(edge[i].p,min(edge[i].w,temp));
temp-=a; edge[i].w-=a; edge[i^].w += a;
if (temp==) break;
}
}
if (temp==low) vis[x]=-;
return low-temp;
}
void bulid(int x){
mem(head,); cnt=;
s=; t=num+pos*x+;
FOR(i,,num) add_edge(s,i,);
FOR(i,,pos*x) add_edge(i+num,t,);
int tmp=;
FO(i,,n) FO(j,,m) if (ss[i][j]=='.') {
++tmp;
FOR(k,,pos) if (node[k].vis[i][j]&&node[k].vis[i][j]<=x) {
FOR(l,node[k].vis[i][j],x) add_edge(tmp,(k-)*x+l+num,);
}
}
}
bool check(int x){
bulid(x);
int sum=, tmp=;
while (bfs()) while (tmp=dfs(s,INF)) sum+=tmp;
return sum==num;
}
int main ()
{
scanf("%d%d",&n,&m);
FO(i,,n) scanf("%s",ss[i]);
FO(i,,n) FO(j,,m) if (ss[i][j]=='.') ++num;
FO(i,,n) FO(j,,m) if (ss[i][j]=='D') {
++pos;
que.push(mp(i,j));
while (!que.empty()) {
PII tmp=que.front();
int x=tmp.first, y=tmp.second; que.pop();
FO(k,,) {
int dx=x+ps[k][], dy=y+ps[k][];
if (dx<||dx>=n||dy<||dy>=m||ss[dx][dy]!='.'||node[pos].vis[dx][dy]) continue;
que.push(mp(dx,dy)); node[pos].vis[dx][dy]=node[pos].vis[x][y]+;
}
}
}
int l=, r=, mid, flag=false;
while (l<r) {
mid=(l+r)>>;
if (check(mid)) r=mid, flag=true;
else l=mid+;
}
if (flag) printf("%d\n",r);
else puts("impossible");
return ;
}

BZOJ 1189 紧急疏散(二分+最大流)的更多相关文章

  1. bzoj 1189 紧急疏散 网络流

    二分答案,网络流判断 将每个门拆点,每个人连向每个门的dis~当前解 然后跑最大流,如果等于人数,即为可行解 #include<cstdio> #include<iostream&g ...

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

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

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

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

  4. [bzoj 1449] 球队收益(费用流)

    [bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...

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

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

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

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

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

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

  8. POJ3228二分最大流

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

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

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

随机推荐

  1. 2016-2017-2 20155338 实验二《Java面向对象程序设计》实验报告

    2016-2017-2 20155338 实验二<Java面向对象程序设计>实验报告 实验内容: 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 3.初步掌握 ...

  2. java开发划分级别的标准

    一.史诗序: java开发也有一段时间了,整天茫茫碌碌,除了偶尔的小有成就感,剩下的大部分好像都在重复,你是否也遇到了这样的情况? 遇到一个小细节问题,之前不久解决过,现在却是什么都记不起来了 面对每 ...

  3. day1 创建X00001文件1K

    要求:创建文件名为:X000001-X999999,大小为1K 的文件 版本1) import os #1.输入要创建的文件数量 nums = int(input("nums:") ...

  4. youtube高清视频下载方法

    youtube下载方法有多种, 但都不支持1080P以上的高清下载, 今天找到一种支持1080P的, 记录一下 步骤1: 百度搜: Dooseen tubedown 下载该软件, 并安装, 一直下一步 ...

  5. 换Mac了,迈入了终端的大门

    多终端其实本质和多线程一样,所有终端其实都共享着同一个内存只不过不同终端对共享内存不同部分的权限不同罢了所以对终端的数量必须要有限制 我这里开启了四个线程,很明显四个线程都在跑同一个内存而且四个线程都 ...

  6. 《机器学习实战》6.2小节,KKT条件代码理解

    <机器学习实战>6.2小节 #这句是检测 当前样本点i 是否满足KKT条件的 if (alphas[i, :] < C and E_i * labelMat[i, :] < - ...

  7. JavaScript 之 ajax

    1. AJAX 的概念 AJAX,即 Asynchronous JavaScript and XML(异步的 JavaScript 和 XML) 同步:前面的代码不执行完毕,后面的代码无法执行 异步: ...

  8. We are writing to let you know we have removed your selling privileges

     Hello, We are writing to let you know we have removed your selling privileges, canceled your listin ...

  9. [leetcode-915-Partition Array into Disjoint Intervals]

    Given an array A, partition it into two (contiguous) subarrays left and right so that: Every element ...

  10. Thunder团队第七周 - Scrum会议2

    Scrum会议2 小组名称:Thunder 项目名称:i阅app Scrum Master:王航 工作照片: 参会成员: 王航(Master):http://www.cnblogs.com/wangh ...