(好题)POJ3057
二分+二分图匹配+BFS
题意:
墙壁“X”,空区域(都是人)“.”, 门“D”。
人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移动。
const int dx[] = {, , , -};
const int dy[] = {, , -, };
int X, Y;
char field[MAXN][MAXN];
vector<int> dX, dY;
vector<int> pX, pY;
int dist[MAXN][MAXN][MAXN][MAXN];
const int MAXV = ;
int V; //顶点数
vector<int> G[MAXV]; //图的邻接表表示
int match[MAXV]; //所匹配的定点
bool used[MAXV]; // DFS中用到的访问标记
//添加无向边,注意顶点编号从0开始
void add_edge(int u, int v) {
G[u].push_back(v);
G[v].push_back(u);
}
//通过DFS寻找增广路
bool dfs(int v) {
used[v] = true;
for (int i = ; i < G[v].size(); i++) {
int u = G[v][i], w = match[u];
if (w < || !used[w] && dfs(w)) {
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
//二分图最大匹配,返回最大匹配数
int Bipartite_Matching() {
int res = ;
memset(match, -, sizeof(match));
for (int v = ; v < V; v++) {
if (match[v] < ) {
memset(used, , sizeof(used));
if (dfs(v)) {
res++;
}
}
}
return res;
}
// 二分,这一点非常精妙
bool C(int t) {
// 0~d-1 时间1跑掉的人
// d~2d-1 时间2跑掉的人
// (t-1)d~td-1 时间t跑掉的人
// td~td+p-1 人
int d = dX.size(), p = pY.size();
V = t * d + p;
REP(i, , V) G[i].clear();
REP(i, , d) REP(j, , p) {
int o = dist[dX[i]][dY[i]][pX[j]][pY[j]];
if (o >= ) {
REP(k, o, t + )
add_edge((k - ) * d + i, t * d + j);
}
}
return Bipartite_Matching() == p;
}
void bfs(int x, int y, int d[MAXN][MAXN]) {
queue<int> qx, qy;
d[x][y] = ;
qx.push(x);
qy.push(y);
while (!qx.empty()) {
x = qx.front(), qx.pop();
y = qy.front(), qy.pop();
REP(i, , ) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= && nx < X && ny >= && ny < Y &&
field[nx][ny] == '.' && d[nx][ny] < ) {
d[nx][ny] = d[x][y] + ;
qx.push(nx);
qy.push(ny);
}
}
}
}
void solve() {
int n = X * Y;
//跑最短路
REP(i, , dX.size()) bfs(dX[i], dY[i], dist[dX[i]][dY[i]]);
//最短路
int lb = -, ub = n + ;
while (ub - lb > ) {
int mid = (ub + lb) / ;
C(mid) ? ub = mid : lb = mid;
}
if (ub > n) {
printf("impossibe\n");
} else {
printf("%d\n", ub);
}
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("input.txt", "r", stdin);
#endif // !ONLINE_JUDGE
int T = READ();
while (T--) {
dX.clear(), dY.clear();
pX.clear(), pY.clear();
CLR(field), SET(dist);
X = READ();
Y = READ();
REP(i, , X) cin >> field[i];
REP(i, , X) REP(j, , Y) {
if (field[i][j] == 'D') {
dX.push_back(i);
dY.push_back(j);
} else if (field[i][j] == '.') {
pX.push_back(i);
pY.push_back(j);
}
}
solve();
}
return ;
}
解法2:
在上述解法下,重复的操作是每次二分都会计算一遍匹配,所以T,那么当T增加时,根据增广路的性质,我们只需要不断增加T,每次加1,就可以找出答案。
这个其实现在也不怎么看懂。
下面是不同的地方,一样的没放上来
void solve() {
int n = X * Y;
//跑最短路
REP(i, , dX.size()) bfs(dX[i], dY[i], dist[dX[i]][dY[i]]);
// 加边
int d = dX.size(), p = pX.size();
V = X * Y * d + p;
for (int v = ; v < V; ++v) G[v].clear();
REP(i, , d) REP(j, , p) {
int o = dist[dX[i]][dY[i]][pX[j]][pY[j]];
if (o >= ) REP(k, o, n + ) add_edge((k - ) * d + i, n * d + j);
}
// 匹配
if (p == ) {
printf("0\n");
return;
}
int num = ; // 匹配数
memset(match, -, sizeof(match));
for (int v = ; v < n * d; v++) {
// n*d是节点总数,每个门一个,把所有情况都跑一遍
memset(used, , sizeof(used));
if (dfs(v)) {
if (++num == p) {
printf("%d\n", v / d + );
return;
}
}
}
printf("impossible\n");
}
(好题)POJ3057的更多相关文章
- POJ3057 Evacuation 二分图匹配+最短路
POJ3057 Evacuation 二分图匹配+最短路 题目描述 Fires can be disastrous, especially when a fire breaks out in a ro ...
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- 【Java每日一题】20170106
20170105问题解析请点击今日问题下方的"[Java每日一题]20170106"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- 【Java每日一题】20170105
20170104问题解析请点击今日问题下方的"[Java每日一题]20170105"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- 【Java每日一题】20170104
20170103问题解析请点击今日问题下方的"[Java每日一题]20170104"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- 【Java每日一题】20170103
20161230问题解析请点击今日问题下方的"[Java每日一题]20170103"查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; ...
- SQL面试笔试经典题(Part 1)
本文是在Cat Qi的原贴的基础之上,经本人逐题分别在MySql数据库中实现的笔记,持续更新... 参考原贴:http://www.cnblogs.com/qixuejia/p/3637735.htm ...
- 刷LeetCode的正确姿势——第1、125题
最近刷LeetCode比较频繁,就购买了官方的参考电子书 (CleanCodeHandbook),里面有题目的解析和范例源代码,可以省去非常多寻找免费经验分享内容和整理这些资料的时间.惊喜的是,里面的 ...
- AWS的SysOps认证考试样题解析
刚考过了AWS的developer认证,顺手做了一下SysOps的样题.以下是题目和答案. When working with Amazon RDS, by default AWS is respon ...
随机推荐
- RainbowPlan团队项目-总结
博客介绍 这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/GeographicInformationScience/ 这个作业要求在哪里 https:// ...
- Kdenlive-开始
版权声明:原创文章,未经博主允许不得转载 这是 Kdenlive 系列文章的第一篇 说明 在 Linux 下的视频编辑的软件并不多,作为其中之一的 kdenlive 在网上的教程就更少了.于是自己琢磨 ...
- python,读取txt的方法和应用
1.读取txt内的百度盘地址,循环保存到百度云中(直接访问下方地址) https://www.cnblogs.com/becks/p/11409467.html 2.读取txt内参数,循环执行查询,读 ...
- python数据类型之字典操作
Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型.一.创建字典字典由key和value成对组成.基本语法如下: infos = {"name&q ...
- python中[-1]、[:-1]、[::-1]、[n::-1]使用方法
import numpy as np a=np.random.rand(5) print(a) [ 0.64061262 0.8451399 0.965673 0.89256687 0.4851874 ...
- Servlet梳理
Servlet 梳理 概述 Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础. 要介绍 Servlet 必须要先把 Servlet 容器 ...
- NLP(十九)首次使用BERT的可视化指导
本文(部分内容)翻译自文章A Visual Guide to Using BERT for the First Time,其作者为Jay Alammar,访问网址为:http://jalammar ...
- 手把手实操教程!使用k3s运行轻量级VM
前 言 k3s作为轻量级的Kubernetes发行版,运行容器是基本功能.VM的管理原本是IaaS平台的基本能力,随着Kubernetes的不断发展,VM也可以纳入其管理体系.结合Container和 ...
- 当你的程序在朋友的机器上显示丢失msvcr100d.dll的时候
0. 给朋友发了个DEMO,收到提示:丢失 msvcr100d.dll 1. 一看是运行库文件,赶紧让朋友下载并安装vc++ 2010 redistribution,朋友反馈还是提示丢失这个dll文件 ...
- lua学习之复习汇总篇
第六日笔记 1. 基础概念 程序块 定义 在 lua 中任何一个源代码文件或在交互模式中输入的一行代码 程序块可以是任意大小的 程序块可以是一连串语句或一条命令 也可由函数定义构成,一般将函数定义写在 ...