题意:

有一个n×m的房间,四周每个格子要么是墙要么是门。中间部分是墙或者人。

现在所有人要从房间逃出去,每个人的速度为1,也就是每个单位时间只能向上下左右四个方向走一格。

多个人可以站在同一个格子上,但是每个时刻每个门只能通过一格人,求所有人从房间中逃出去所需要的最少时间。

分析:

把每个人看成一个点,然后把每个时刻和门组成的二元组看成一个点。

如果两点之间连一条边表示这个人在这个时刻从这个门逃出去。

所以我们可以从小到大将时间逐渐加1,直到找到最大匹配为止。

在增加点的时候,可以在之前最大流基础上增广,这样更快。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#define MP make_pair
using namespace std; typedef pair<int, int> PII; const int INF = 0x3f3f3f3f;
const int maxh = ;
const int maxnode = ; char maze[maxh][maxh];
int id[maxh][maxh]; int row, col; vector<PII> people, doors; int dx[] = { , , -, };
int dy[] = { , , , - }; int dist[][]; //the distance from every door to people
int steps[maxh][maxh]; bool inline in(int x, int y) { return x >= && x < row && y >= && y < col; } bool vis[maxh][maxh]; void bfs(PII s)
{
int st = id[s.first][s.second];
steps[s.first][s.second] = ;
queue<PII> Q;
Q.push(s);
memset(vis, false, sizeof(vis));
vis[s.first][s.second] = true; while(!Q.empty())
{
PII t = Q.front(); Q.pop();
for(int i = ; i < ; i++)
{
int x = t.first + dx[i];
int y = t.second + dy[i];
if(in(x, y) && !vis[x][y] && maze[x][y] == '.')
{
vis[x][y] = true;
dist[st][id[x][y]] = steps[x][y] = steps[t.first][t.second] + ;
Q.push(MP(x, y));
}
}
}
} struct Edge
{
int from, to, cap, flow;
Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {}
}; int nodes;
vector<int> G[maxnode];
vector<Edge> edges; void init()
{
edges.clear();
for(int i = ; i < nodes; i++) G[i].clear();
} void AddEdge(int u, int v, int cap)
{
edges.push_back(Edge(u, v, cap, ));
edges.push_back(Edge(v, u, , ));
int m = edges.size();
G[u].push_back(m - );
G[v].push_back(m - );
} int s, t;
bool visit[maxnode];
int d[maxnode], cur[maxnode]; bool BFS()
{
memset(visit, false, sizeof(visit));
queue<int> Q;
Q.push(s);
d[s] = ;
visit[s] = true; while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i = ; i < G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
int v = e.to;
if(!visit[v] && e.cap > e.flow)
{
visit[v] = true;
Q.push(v);
d[v] = d[u] + ;
}
}
} return visit[t];
} int DFS(int u, int a)
{
if(u == t || a == ) return a;
int flow = , f;
for(int& i = cur[u]; i < G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
int v = e.to;
if(d[v] == d[u] + && (f = DFS(v, min(a, e.cap - e.flow))) > )
{
e.flow += f;
edges[G[u][i]^].flow -= f;
flow += f;
a -= f;
if(a == ) break;
}
}
return flow;
} int Maxflow()
{
int flow = ;
while(BFS())
{
memset(cur, , sizeof(cur));
flow += DFS(s, INF);
}
return flow;
} void Readuce()
{
for(int i = ; i < edges.size(); i++)
edges[i].cap -= edges[i].flow, edges[i].flow = ;
} int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d%d", &row, &col);
for(int i = ; i < row; i++) scanf("%s", maze[i]); memset(id, , sizeof(id));
people.clear(); doors.clear();
int psz = , dsz = ;
for(int i = ; i < row; i++)
for(int j = ; j < col; j++)
{
if(maze[i][j] == 'D') { doors.push_back(MP(i, j)); id[i][j] = dsz++; }
else if(maze[i][j] == '.') { people.push_back(MP(i, j)); id[i][j] = psz++; }
} memset(dist, 0x3f, sizeof(dist));
for(int i = ; i < dsz; i++) bfs(doors[i]);
bool unreachable = false;
for(int i = ; i < psz; i++)
{
bool reach = false;
for(int j = ; j < dsz; j++)
if(dist[j][i] < INF) { reach = true; break; }
if(reach == false) { unreachable = true; break; }
} if(unreachable) { puts("impossible"); continue; } int tot_time = ;
s = , t = ;
nodes = + psz;
init();
for(int i = ; i < psz; i++) AddEdge(s, i + , ); int matches = ;
for(;;)
{
tot_time++;
for(int i = ; i < dsz; i++)
{
G[nodes].clear();
AddEdge(nodes, t, );
for(int j = ; j < psz; j++)
if(dist[i][j] <= tot_time) AddEdge(j + , nodes, );
nodes++;
}
matches += Maxflow();
if(matches == psz) break;
Readuce();
}
printf("%d\n", tot_time);
} return ;
}

代码君

POJ 3057 网络流 Evacuation的更多相关文章

  1. POJ 3057 Evacuation 二分+最大流

    Evacuation 题目连接: http://poj.org/problem?id=3057 Description Fires can be disastrous, especially when ...

  2. POJ 3057 Evacuation(二分图匹配+BFS)

    [题目链接] http://poj.org/problem?id=3057 [题目大意] 给出一个迷宫,D表示门,.表示人,X表示不可通行, 每个门每时间单位只允许一个人通过, 每个人移动一格的为一时 ...

  3. [poj] 3057 Evacuation

    原题 题目大意 墙壁"X",空区域(都是人)".", 门"D". 人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移 ...

  4. POJ 3057 Evacuation 题解

    题目 Fires can be disastrous, especially when a fire breaks out in a room that is completely filled wi ...

  5. 【最大匹配+二分答案】POJ 3057 Evacuation

    题目大意 POJ链接 有一个\(X×Y\)的房间,X代表墙壁,D是门,.代表人.这个房间着火了,人要跑出去,但是每一个时间点只有一个人可以从门出去. 问最后一个人逃出去的最短时间,如果不能逃出去,输出 ...

  6. POJ 3057 Evacuation 二分图匹配

    每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:10240000 ...

  7. POJ 3057 Evacuation (二分匹配)

    题意:给定一个图,然后有几个门,每个人要出去,但是每个门每个秒只能出去一个,然后问你最少时间才能全部出去. 析:初一看,应该是像搜索,但是怎么保证每个人出去的时候都不冲突呢,毕竟每个门每次只能出一个人 ...

  8. POJ 3057 Evacuation(二分匹配)

    分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d ...

  9. TTTTTTTTTTTTT poj 3057 Evacuation 二分图匹配+bfs

    题意:见挑战230页 #include <iostream> #include <cstdio> #include <cstring> #include <c ...

随机推荐

  1. watir 的api在线文档

    http://rubydoc.info/gems/watir-webdriver/frames http://rdoc.info/gems/watir-webdriver/frames http:// ...

  2. edittext 设置不自动获取焦点

    给父级控件 设置两个属性,可以把焦点抢夺过去,最好是没有任何事件的父级控件(本人比较喜欢在xml文件的跟布局设置,因为页面的跟布局一般情况下,是不会设置任何事件的) android:focusable ...

  3. Volley解析(一)--Volley的使用

    Volley解析(一)--Volley的使用 Volley 是一个HTTP协议的网络请求框架 Volley的优势: 自动安排网络请求 支持多个并发网络连接 具有标准HTTP缓存一致性的透明磁盘和内存响 ...

  4. MySQL-基本概念

    一.Mysql逻辑架构 引用自<高性能Mysql> 二.并发控制 读写锁:读锁是共享的,写锁是排他的,会阻塞其他的写锁和读锁. 锁粒度:表锁.行级锁 三.事务 事务(ACID特性):原子性 ...

  5. 一键部署WordPress开源内容管理系统

    https://market.azure.cn/Vhd/Show?vhdId=9857&version=10889 产品详情 产品介绍WordPress是一款个人博客系统,并逐步演化成一款内容 ...

  6. SQL Server 查询性能优化——创建索引原则

    索引是什么?索引是提高查询性能的一个重要工具,索引就是把查询语句所需要的少量数据添加到索引分页中,这样访问数据时只要访问少数索引的分页就可以.但是索引对于提高查询性能也不是万能的,也不是建立越多的索引 ...

  7. 学习Unity 4.6新GUI系统

    (搬运自我在SegmentFault的博客) 最近在学习Unity的过程中,自己做一款小游戏自娱自乐.自然需要用到GUI.但4.5中的GUI很难用,一个选择是传说中的NGUI插件.但对于4.6中的新G ...

  8. A winner is a dreamer who never gives up

    A winner is a dreamer who never gives up. 成功者是坚持梦想不放弃的人.(Nelson Mandela)

  9. MySQL安装未响应解决方法

    安装MySQL出示未响应,一般显示在安装MySQL程序最后2步的3,4项就不动了. 这种情况一般是你以前安装过MySQL数据库服务项被占用了. 1.卸载MySQL 2.删除安装目录及数据存放目录 3. ...

  10. HDU - 5493 Queue 2015 ACM/ICPC Asia Regional Hefei Online(线段树)

    按身高排序,每个人前面最高的人数有上限,如果超出上限说明impossible, 每次考虑最小的人,把他放在在当前的从左往右第k+1个空位 因为要求字典序最小,所以每次k和(上限-k)取min值. 没有 ...