POJ Evacuation /// 二分图最大匹配
题目大意:
在一个n*m的房间中 ‘X’为墙 ‘D’为门 ‘.’为人
门只存在与外围 人每秒钟只能向四连通区域走一步
门比较狭窄 每秒钟只能通过一个人
求所有人逃脱的最短时间 如果不可能则输出impossible
对每个门 广搜出能在这个门逃脱的人的逃出时间
将 对应各个时间的这个门 当做不同的点
即 若有d个门 p个人
时间1对应的门编号为 0~d-1
时间2对应的门编号为 d~2*d-1
时间t对应的门编号为 (t-1)*d~t*d-1
然后将人编号为 t*d~t*d+p-1
再将 对应时间的门的编号 与 对应时间在该门逃脱的人 连边
而一个人若能在 t 时间逃脱 那么同样可以在 t+1、t+2、t+3...时间逃脱
所以 对应时间到最晚时间的该门的编号 都可与 这个人连边
这样找到 各个时间的门 与 人 的最大匹配
时间从小到大 这样判断到最大匹配数恰好等于人数时说明此时所有人都可逃脱
#include <bits/stdc++.h>
using namespace std;
int n,m;
char G[][];
int mov[][]={,,,,,-,-,}; int dis[][][][];
// dis[x][y][i][j] 门的位置为xy 人的位置为ij 保存逃脱的最短用时
struct NODE { int x,y; };
vector <NODE> D, P; // D记录门的位置 P记录人的位置 const int E=***;
vector <int> e[E]; // 邻接表 bool bound(int x1,int y1) {
return x1< || x1>=n || y1< || y1>=m;
}
void bfs(int x1,int y1,int d[][]) {
// d为dis[x1][y1]对应的后两维
queue <NODE> q;
q.push((NODE){x1,y1});
d[x1][y1]=;
while(!q.empty()) {
NODE e=q.front(); q.pop();
for(int i=;i<;i++) {
int x2=e.x+mov[i][], y2=e.y+mov[i][];
if(bound(x2,y2) || d[x2][y2]!=-) continue;
if(G[x2][y2]!='.') continue;
d[x2][y2]=d[e.x][e.y]+;
q.push((NODE){x2,y2});
}
}
}
/**二分图最大匹配*/
bool vis[E];
int mat[E];
bool dfs(int u) {
vis[u]=;
for(int i=;i<e[u].size();i++) {
int v=e[u][i], d=mat[v];
if(d==- || !vis[d]&&dfs(d)) {
mat[u]=v, mat[v]=u;
return ;
}
}
return ;
}
int match(int d,int p) {
int res=;
memset(mat,-,sizeof(mat));
for(int i=;i<n*d;i++) // 时间从小到大 一旦找到最大匹配就是最快逃脱时间
if(mat[i]==-) {
memset(vis,,sizeof(vis));
if(dfs(i)) {
res++;
if(res==p) return i/d+;
/// 一旦匹配数等于人数 说明此时所有人都已匹配
}
}
return ;
}
/***/ void solve() {
memset(dis,-,sizeof(dis));
D.clear(), P.clear();
for(int i=;i<n;i++) {
for(int j=;j<m;j++)
if(G[i][j]=='D') {
D.push_back((NODE){i,j});
bfs(i,j,dis[i][j]);// 广搜出所有能到ij门的人的最短时间
} else if(G[i][j]=='.')
P.push_back((NODE){i,j});
} n*=m;
for(int i=;i<E;i++) e[i].clear();
int d=D.size(), p=P.size();
for(int i=;i<d;i++) {
for(int j=;j<p;j++) {
int t=dis[D[i].x][D[i].y][P[j].x][P[j].y];
if(t!=-) { // 说明最快t时间可以逃脱
for(int k=t;k<=n;k++) // 则t以上时间都可逃脱 连边
e[(k-)*d+i].push_back(n*d+j);
}
}
} if(p==) {
printf("0\n"); return;
}
int ans=match(d,p);
if(ans) printf("%d\n",ans);
else printf("impossible\n");
} int main()
{
int t; scanf("%d",&t);
while(t--) {
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
scanf("%s",G[i]);
solve();
} return ;
}
POJ Evacuation /// 二分图最大匹配的更多相关文章
- poj 2239 二分图最大匹配,基础题
1.poj 2239 Selecting Courses 二分图最大匹配问题 2.总结:看到一个题解,直接用三维数组做的,很巧妙,很暴力.. 题意:N种课,给出时间,每种课在星期几的第几节课上 ...
- POJ 2226二分图最大匹配
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...
- poj 2724 二分图最大匹配
题意: 会给出M个串,我们要做的就是将这M个串给清除了.对于任意两个串,若二进制形式只有一位不一样,那么这两个串可以在一次操作消除,否则每个操作只能消除一个串. 3 3 *01 100 011 可以代 ...
- Asteroids - poj 3041(二分图最大匹配问题)
Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 17258 Accepted: 9386 Description Be ...
- poj 2446 二分图最大匹配
思路:由(i+j)为偶数的点向(i+j)为奇数的点建边.求一次最大匹配,若正好为空格数(不包含洞)的一半,即输出YES. #include<iostream> #include<cs ...
- poj 1469 二分图最大匹配
就是最简单的最大匹配,没的说 #include<iostream> #include<cstdio> #include<cstring> #include<a ...
- poj 1469(二分图 最大匹配)
这道题让我认识到了c++cin,cout确实会使其超时,还是我用的c printf吧 #include<cstdio> #include<iostream> #include& ...
- POJ 1719 二分图最大匹配(记录路径)
Shooting Contest Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 4097 Accepted: 1499 ...
- poj 3692 二分图最大匹配
思路: 如果我们将认识的建边,求最大独立集就是互相不认识的人数.那么我们反过来,将不认识的建图,求最大独立集就是互相认识的人数. #include<cstdio> #include< ...
随机推荐
- CSS:CSS 属性 选择器
ylbtech-CSS:CSS 属性 选择器 1.返回顶部 1. CSS 属性 选择器 具有特定属性的HTML元素样式 具有特定属性的HTML元素样式不仅仅是class和id. 注意:IE7和IE8需 ...
- python re模块使用
re.findall() 查找字符 从字符串中找出符合模式的字符序列:findall(模式(正则表达式),目标字符串), 返回值为list类型,list元素为匹配出的各个字符串如: import re ...
- Socket通信1.0
Socket通信1.0 服务器端: package page; import java.io.BufferedReader; import java.io.IOException; import ja ...
- 18、Page Object 设计模式
Page Object 设计模式的优点如下: 减少代码的重复. 提高测试用例的可读性. 提高测试用例的可维护性, 特别是针对 UI 频繁变化的项目. 当你针对网页编写测试时,你需要引用该网页中的元素, ...
- Java类初始化顺序,大神3个示例带你躺坑。。
最近发现微信群里面有些群友在讨论类的初始化顺序,如类的静态变量.成员变量.静态代码块.非静态代码块.构造器,及继承父类时,它们的初始化顺序都是怎样的,下面我通过例子来说明这个情况,以免被人误导. 示例 ...
- java-day19
获取Stream流方法 根据Collection获取流 根据Map获取流 根据数组获取流 常用方法分为两种:延迟方法和终结方法 逐一处理:forEach 过滤:filter 映射:map 统计个数:c ...
- pytest-mark跳过
import pytestimport sysenvironment='android' @pytest.mark.skipif(environment=="android",re ...
- 解析TextView中的URL等指定特殊字符串与点击事件
使用TextView时,有时可能需要给予TextView里的特定字符串,比如URL,数字特别的样式,必希望能够添加点击事件.比如发短信时,文字里的url就可以点击直接打开浏览器,数字可以点击拨打电话. ...
- 【HDOJ】P1007 Quoit Design (最近点对)
题目意思很简单,意思就是求一个图上最近点对. 具体思想就是二分法,这里就不做介绍,相信大家都会明白的,在这里我说明一下如何进行拼合. 具体证明一下为什么只需要检查6个点 首先,假设当前左侧和右侧的最小 ...
- python--面向对象:类和对象命名空间
一.一个类可以定义两种属性:静态属性和动态属性 (一)对于不可变数据类型来说,类变量最好用类名操作,也可以用对象操作,但是只能查,不能改,对象改的都只是相当于在自己的命名空间里重新建立了一个 clas ...