POJ 3057 网络流 Evacuation
题意:
有一个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的更多相关文章
- POJ 3057 Evacuation 二分+最大流
Evacuation 题目连接: http://poj.org/problem?id=3057 Description Fires can be disastrous, especially when ...
- POJ 3057 Evacuation(二分图匹配+BFS)
[题目链接] http://poj.org/problem?id=3057 [题目大意] 给出一个迷宫,D表示门,.表示人,X表示不可通行, 每个门每时间单位只允许一个人通过, 每个人移动一格的为一时 ...
- [poj] 3057 Evacuation
原题 题目大意 墙壁"X",空区域(都是人)".", 门"D". 人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移 ...
- POJ 3057 Evacuation 题解
题目 Fires can be disastrous, especially when a fire breaks out in a room that is completely filled wi ...
- 【最大匹配+二分答案】POJ 3057 Evacuation
题目大意 POJ链接 有一个\(X×Y\)的房间,X代表墙壁,D是门,.代表人.这个房间着火了,人要跑出去,但是每一个时间点只有一个人可以从门出去. 问最后一个人逃出去的最短时间,如果不能逃出去,输出 ...
- POJ 3057 Evacuation 二分图匹配
每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:10240000 ...
- POJ 3057 Evacuation (二分匹配)
题意:给定一个图,然后有几个门,每个人要出去,但是每个门每个秒只能出去一个,然后问你最少时间才能全部出去. 析:初一看,应该是像搜索,但是怎么保证每个人出去的时候都不冲突呢,毕竟每个门每次只能出一个人 ...
- POJ 3057 Evacuation(二分匹配)
分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d ...
- TTTTTTTTTTTTT poj 3057 Evacuation 二分图匹配+bfs
题意:见挑战230页 #include <iostream> #include <cstdio> #include <cstring> #include <c ...
随机推荐
- LCA 离线做法tarjan
tarjan(int u) { int v; for(int i=h[u];i;i=nex[i])//搜索边的 { v=to[i]; tarjan(v); marge(u,v); vis[v]=; } ...
- JFileChooser 打开文件选择(一)
import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; public clas ...
- SQL概念及DDL语句
SQL概念 SQL全称(Structured Query Language):结构化查询语句,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询和管理关系型数据库. 其实就 ...
- npm使用快速的安装源(nrm)
安装 npm install nrm --global 使用 nrm ls 切换安装源 nrm use taobao 测速 nrm test npm 参考地址:http://codingdict.co ...
- 真正的S2b其实是S2b2c
本文转自阿里参谋长曾鸣:真正的S2b其实是S2b2c! 在<在未来五年,S2b是最有可能领先的商业模式>这篇文章发表之后,曾鸣书院收到了非常多的反馈,看到很多实践和思考. 在这篇文章中,曾 ...
- JAVA-WEB总结01
1 工具常用的快捷键 1) Eclipse和MyEclipse,IBM,2001,Java编写,开源,跨平台跨语言 2)Alt+/快速内容提示(自己习惯定义) 3)Ctrl+1快速修补错误 ...
- 【TensorFlow入门完全指南】神经网络篇·MLP多层感知机
前面的不做过多解释了. 这里定义了两个占位符,各位也知道,在训练时,feed_dict会填充它们. 定义相关网络. 这里是权值矩阵和偏差. 这里是实例化了网络,定义了优化器和损失,和上一篇一样. 最后 ...
- Android(java)学习笔记132:eclipse 导入项目是提示:某些项目因位于工作空间目录中而被隐藏。
导致这个错误的原因是工程重名了: 并不是仅仅指文件夹重名,相信很多人也曾经修改过文件夹的名称,可惜没什么用处,关键是修改工程里面的一个文件! 也就是.project这个文件! 用记事本打开,修改一下& ...
- [web开发] Vue + spring boot + echart 微博爬虫展示平台
1.微博登录 2.爬取数据 3.mysql存储 4.pyechart本地展示 5.用vue搭建网站web展示 先放图: 1.微博登录 新浪微博的登录不是简单的post就能解决的,他的登录有加密,所以我 ...
- python_106_创建类的两种方式
class Foo(object): def __init__(self, name): self.name = name f = Foo("alex") print(type(f ...