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 ...
随机推荐
- text-transform 字母的大小写
text-transform: none 默认 capitalize 每个单词以大写字母开头 uppercase 仅有大写字母 lowercase 无大写字母,仅有小写字母 i ...
- SpringMVC+Thymeleaf 简单使用
一.简介 1.Thymeleaf 在有网络和无网络的环境下皆可运行,而且完全不需启动WEB应用,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果.浏览器解释 h ...
- nginx只允许域名访问网址,禁止ip访问
修改nginx配置 文件 在server段里插入如下正则: if ( $host != 'www.baidu.com') { return 403; } 说明:如果访问讨还不是www.baidu.co ...
- 洛谷——普及练习场 普及组选手可冲刺训练,提高组选手亦可在此巩固基础。(Loading...)
简单的模拟 关卡2-1,6 道题 开始普及组的训练!所谓模拟,就是直接根据题意编写,思维难度简单. //T1 铺地毯 #include <cstdio> #define N 10005 i ...
- python基础教程总结15——4 新闻聚合
NNTP:网络新闻传输协议,Network News Transfer Protocol 目标: 从多种不同的来源收集新闻: 用户可以轻松添加新的新闻来源(甚至是新类型的新闻来源: 程序可以将编译好的 ...
- UVA1602 Lattice Animals 网格动物 (暴力,STL)
多联骨牌的生成办法,维基上只找到固定的骨牌fix,而free的没有找到. 于是只好写个set判重的简单枚举了. 旋转的操作,可以在坐标轴上画个点,以原点为轴心,逆时针旋转90度,新的点的坐标为(-y, ...
- Ubuntu 16.04 换国内源
官方渠道,图形界面,操作简单,可以说对新手及其友好!! 依次打开:搜索,软件与更新,第一个和第三个勾上,下载自,其它,然后在中国条目下选择你想使用的镜像站点,然后点“选择服务器”,然乎点击“关闭”,选 ...
- gzip, gunzip, zcat - 压缩或展开文件
总揽 gzip [ -acdfhlLnNrtvV19 ] [-S 后缀] [ 文件名 ... ] gunzip [ -acfhlLnNrtvV ] [-S 后缀] [ 文件名 ... ] zcat [ ...
- 分类回归树(CART)
概要 本部分介绍 CART,是一种非常重要的机器学习算法. 基本原理 CART 全称为 Classification And Regression Trees,即分类回归树.顾名思义,该算法既 ...
- CPP-基础:C/C++数组名与指针的区别
2005-08-23 08:36 来源:天极网 作者:宋宝华 责任编辑:方舟·yesky 引言 指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很 ...