(好题)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 ...
随机推荐
- 为磁盘文件定义路由(Defining Routes for Disk Files) |对磁盘文件进行路由请求 |
- Dynamics CRM CE 怎样从 UCI 改为 classic UI
dynamics 现在大力推UCI. 但是对于大部分人来说还是使用不习惯. 怎样从UCI改为classic UI呢 1. 快速的方法 https://xxx.crm.dynamics.com/main ...
- ReactNative---组件种类
- Linux 常用工具openssh之scp
前言 scp命令用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器硬盘变为只读read ...
- nmap详解之原理与用法
前言 nmap是一款开源免费的网络发现(Network Discovery)和安全审计(Security Auditing)工具.软件名字Nmap是Network Mapper的简称.Nmap最初是由 ...
- react中 如何使用图片
//render 第一种方法:先const一个对象,把需要应用图片的dom上的style写入对象中, 然后在return()中使用style关键字赋值为预先定义的那个style对象 const bgG ...
- C++ 强制类型转换详解
类型转换只不过是让编译器以另外一种方式解释一块内存而已.C++兼容C语言的强制类型转换方式,同时也提供了新型的基于模板的类型转换方式,来提供更多的安全性. 一.C风格的强制类型转换 double k ...
- provider networks和self-service networks
Provider Network 服务布局 Self-Service Network 网络布局: 网络布局 Provider Networks概述 Provider networks - Conne ...
- Bayesian Non-Exhaustive Classification A case study:online name disambiguation using temporal record streams
一 摘要: name entity disambiguation:将对应多个人的记录进行分组,使得每个组的记录对应一个人. 现有的方法多为批处理方式,需要将所有的记录输入给算法. 现实环境需要1:以o ...
- ant编译solr源码生成eclipse项目,解决一直resolve,一直[ivy:retrieve]的问题
这两天在学习solr,结果刚到编译solr源码就卡住了,足足卡了两天,网上找各种解决办法都是简单带过,说是缺少jar包,下载下来放到对应位置就好了....对应位置???咋不说这个问题用相应方法解决即可 ...