我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利去check就行了...其实这道题挺好想但是码量还是挺大的....

-----------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
 
using namespace std;
 
#define chk(r, c) (r >= 0 && r < N && c >= 0 && c < M)
 
const int maxn = 29;
const int MAXN = 330;
const int MAX_V = 80;
const int INF = 0X3F3F3F3F;
const int dir[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};
 
struct edge {
int to;
edge* next;
} E[8000000], *pt, *head[MAXN];
 
void InitEdge() {
pt = E;
memset(head, 0, sizeof head);
}
 
void AddEdge(int u, int v) {
pt->to = v; pt->next = head[u]; head[u] = pt++;
}
 
int D[MAX_V][MAXN];
int R[MAXN], C[MAXN], _R[MAX_V], _C[MAX_V], Id[maxn][maxn];
int vis[MAXN * MAXN], mch[MAXN * MAXN];
int CK, N, M, V, _V;
char s[maxn][maxn];
queue<int> Q;
 
bool Dfs(int x) {
for(edge* e = head[x]; e; e = e->next) if(vis[e->to] != CK) {
vis[e->to] = CK;
if(!~mch[e->to] || Dfs(mch[e->to])) {
mch[e->to] = x;
return true;
}
}
return false;
}
 
void BFS(int x) {
memset(D[x], INF, sizeof D[x]);
while(!Q.empty()) Q.pop();
int X = _R[x], Y = _C[x];
if((X == N - 1 && Y == M - 1) || (!X && !Y)) return;
if(!X && ~Id[X + 1][Y]) {
Q.push(Id[X + 1][Y]);
D[x][Id[X + 1][Y]] = 0;
}
if(X == N - 1 && ~Id[X - 1][Y]) {
Q.push(Id[X - 1][Y]);
D[x][Id[X - 1][Y]] = 0;
}
if(!Y&& ~Id[X][Y + 1]) {
Q.push(Id[X][Y + 1]);
D[x][Id[X][Y + 1]] = 0;
}
if(Y == M - 1 && ~Id[X][Y - 1]) {
Q.push(Id[X][Y - 1]);
D[x][Id[X][Y - 1]] = 0;
}
while(!Q.empty()) {
int v = Q.front(); Q.pop();
int r = R[v], c = C[v];
for(int i = 0; i < 4; i++) {
int _r = r + dir[i][0], _c = c + dir[i][1];
if(!chk(_r, _c) || s[_r][_c] != '.') continue;
int _v = Id[_r][_c];
if(~_v && D[x][v] + 1 < D[x][_v]) {
D[x][_v] = D[x][v] + 1;
Q.push(_v);
}
}
}
}
 
void Init() {
memset(Id, -1, sizeof Id);
V = _V = 0;
scanf("%d%d", &N, &M);
for(int i = 0; i < N; i++) {
scanf("%s", s[i]);
for(int j = 0; j < M; j++) switch(s[i][j]) {
case '.' : R[V] = i; C[V] = j; Id[i][j] = V++; break;
case 'D' : _R[_V] = i; _C[_V] = j; Id[i][j] = _V++; break;
default : break;
}
}
for(int i = 0; i < _V; i++) BFS(i);
}
 
void InitArray() {
memset(vis, -1, sizeof vis);
memset(mch, -1, sizeof mch);
}
 
bool Jud(int m) {
InitEdge();
InitArray();
for(int i = 0; i < _V; i++) {
int B = i * m;
for(int j = 0; j < V; j++)
for(int k = D[i][j]; k < m; k++)
AddEdge(j, B + k);
}
int cnt = 0;
for(CK = 0; CK < V; CK++)
if(Dfs(CK)) cnt++;
return cnt == V;
}
 
bool Imp() {
memset(vis, 0, sizeof vis);
for(int i = 0; i < _V; i++)
for(int j = 0; j < V; j++)
if(D[i][j] != INF) vis[j] = -1;
for(int i = 0; i < V; i++)
if(~vis[i]) return false;
return true;
}
 
int main() {
Init();
if(!Imp()) {
puts("impossible"); return 0;
}
int l = 1, r = V, ans = 0;
while(l <= r) {
int m = (l + r) >> 1;
if(Jud(m))
ans = m, r = m - 1;
else
l = m + 1;
}
printf("%d\n", ans);
return 0;
}

-----------------------------------------------------------------------------

1189: [HNOI2007]紧急疏散evacuate

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1219  Solved: 448
[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

Source

BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )的更多相关文章

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

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

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

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

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

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

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

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

  5. 【洛谷 P3191】 [HNOI2007]紧急疏散EVACUATE(二分答案,最大流)

    题目链接 sb错误调了3hour+.. bfs预处理出每个\(.\)到每个\(D\)的最短距离. 二分时间\(t\),把每个\(D\)拆成\(t\)个点,这\(t\)个点两两连边,流量\(INF\)表 ...

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

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

  7. 【bzoj1189】[HNOI2007]紧急疏散evacuate BFS最短路+动态加边网络流

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

  8. 1189: [HNOI2007]紧急疏散evacuate

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3831  Solved: 1119[Submit][Status][Discuss] Descript ...

  9. BZOJ1189 [HNOI2007]紧急疏散evacuate 【二分 + 网络流】

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

随机推荐

  1. html 基本标签

    HTML 基本标签 Web 服务器工作原理 HTML 注释 HTML 基本标签 http://192.168.32.36:8080/scan/demo.html scan 表示你的应用资源目录 HTM ...

  2. nginx File not found 错误分析与解决方法

    使用php-fpm解析PHP,出错提示如下:"No input file specified","File not found",原因是php-fpm进程找不到 ...

  3. Eclipse无法识别(手机)设备的解决方案

    遇到问题 开始学习android一个多月了,用Eclipse开发,用android手机调试.之前一直好好的,突然Eclipse无法识别手机设备了.纠结了好久,找了各种解决方法,弄了一晚上终于解决问题了 ...

  4. MySQL数据处理函数

    数据处理函数 有时从数据库表中获取到的数据须要进行一些处理. 如将小写字母替换为对应的大写字母.这个处理过程能够在客户机上进行.也能够在数据库上进行. 数据库上进行会更高效.数据库中有对应的数据处理函 ...

  5. Node.cloneNode()方法

    概述 返回调用该方法的节点的一个副本. 语法 var dupNode = node.cloneNode(deep);node将要被克隆的节点dupNode克隆生成的副本节点deep 可选是否采用深度克 ...

  6. js简繁转换,两种实现方式,妥妥的~

    不知道繁简按钮有什么卵用,大陆人自带繁简转换开关的好么,但是还是项目要求,做了这么一个功能,现在整理给大家用~完美兼容~么么哒 按钮的样式可以随便用css定义,注意id不要变,注意jq的事件绑定好就o ...

  7. 软件开发常用Linux命令

    解压缩 tar -zxvf xxx.tar.gz 文件显示及查找常用于分析log //显示file中包含aaa的行 cat <file>|grep aaa 查看cpu memory基本信息 ...

  8. iOS隐藏tabBar的方法

    两种方法用来隐藏tabBar 1.在本页面隐藏 #pragma mark - 隐藏tabBar - (void)viewWillAppear:(BOOL)animated{ self.tabBarCo ...

  9. android—资源文件(res)的引用

    android项目中res目录下的文件含义各不相同主要有两种方式引用它们 例子:在string.xml中定义一个<string name="hello">Hello W ...

  10. C++类的常成员函数

    让一个成员函数带上常量性是什么意思呢?通常的答案是,一个常成员函数不会更改其class对象.这是一种平凡的表述,而编译器实现的手法也相当平凡. 任何非静态成员函数其实都被编译器隐式插入了一个指针类型的 ...