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 ...
随机推荐
- [luogu 1967]货车运输
货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情 ...
- wpf ComboBox的SelectionBoxItem相关依赖属性
以前没有注意SelectionBoxItem相关依赖属性,这几天看wpf源码 特意研究了一番 <Style x:Key="ComboBoxStyle1" TargetType ...
- JSONModel 简单例子
// ProductModel.h // JSONModel // // Created by 张国锋 on 15/7/20. // Copyright (c) 2015年 张国锋. All righ ...
- dubbo服务降级(2)
dubbo降级服务 使用dubbo在进行服务调用时,可能由于各种原因(服务器宕机/网络超时/并发数太高等),调用中就会出现RpcException,调用失败. 服务降级就是指在由于非业务异常导致的服务 ...
- 洛谷 P1821 [USACO07FEB]银牛派对Silver Cow Party
银牛派对 正向建图+反向建图, 两边跑dijkstra,然后将结果相加即可. 反向建图以及双向建图的做法是学习图论的必备思想. #include <iostream> #include & ...
- 评价PE基金绩效的常用指标
作为信息系统,辅助管理层决策是重要的功能之一.前文介绍了PE基金管理系统的建设,对PE业务的运转有了一些了解,但没有介绍如何评价PE基金的绩效,而这是管理层作出重大决策的主要依据之一.PE基金本质也是 ...
- RK3288开发过程中遇到的问题点和解决方法之Framework
删除小电池图标及百分比 a.SystemUI/.../statusbar/policy/BatteryController.java mBatteryPercentageView.setVisibil ...
- 读写属性/if判断那点事/数组
读写属性属性操作注意事项 js中不允许出现"-".所以font-size变成fontSize/margin-top变成marginTop. Op.style.with=" ...
- eclipse3.4+对的处理插件(附SVN插件安装实例)
Eclipse 3.4以前安装插件无非有两种方式, 直接copy插件到features/plugins目录或者在links目录下创建链接文件. Eclipse 3.4又推出另一种新的安装途径, 更加灵 ...
- 问题驱动的Git学习
(搬运自我在SegmentFault的博客) 本人是个Git新手,平时用Git最多的就是push,因为别的都不怎么会用.这几天因为在小组中负责代码的整合,顺便将代码提交到Github,接触到了Git更 ...