题目大意:

在一个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 /// 二分图最大匹配的更多相关文章

  1. poj 2239 二分图最大匹配,基础题

    1.poj 2239   Selecting Courses   二分图最大匹配问题 2.总结:看到一个题解,直接用三维数组做的,很巧妙,很暴力.. 题意:N种课,给出时间,每种课在星期几的第几节课上 ...

  2. POJ 2226二分图最大匹配

    匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...

  3. poj 2724 二分图最大匹配

    题意: 会给出M个串,我们要做的就是将这M个串给清除了.对于任意两个串,若二进制形式只有一位不一样,那么这两个串可以在一次操作消除,否则每个操作只能消除一个串. 3 3 *01 100 011 可以代 ...

  4. Asteroids - poj 3041(二分图最大匹配问题)

      Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17258   Accepted: 9386 Description Be ...

  5. poj 2446 二分图最大匹配

    思路:由(i+j)为偶数的点向(i+j)为奇数的点建边.求一次最大匹配,若正好为空格数(不包含洞)的一半,即输出YES. #include<iostream> #include<cs ...

  6. poj 1469 二分图最大匹配

    就是最简单的最大匹配,没的说 #include<iostream> #include<cstdio> #include<cstring> #include<a ...

  7. poj 1469(二分图 最大匹配)

    这道题让我认识到了c++cin,cout确实会使其超时,还是我用的c printf吧 #include<cstdio> #include<iostream> #include& ...

  8. POJ 1719 二分图最大匹配(记录路径)

    Shooting Contest Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4097   Accepted: 1499 ...

  9. poj 3692 二分图最大匹配

    思路: 如果我们将认识的建边,求最大独立集就是互相不认识的人数.那么我们反过来,将不认识的建图,求最大独立集就是互相认识的人数. #include<cstdio> #include< ...

随机推荐

  1. /etc/X11/xorg.conf

    # This configuration file was broken by system-config-keyboard Section "ServerLayout" Iden ...

  2. hibernate5.2.10.Final基本配置

    1.在官网去下载,解压后在lib/required目录下的所有jar包都是必要的. 2.为了之后配置方便,建议在eclipse里面安装一个东东,操作步骤是在eclipse->Help->I ...

  3. build protobuf to a static library

    use ar cd src ar -cvq libprotobuf.a *.o

  4. CSS Sprite初探之原理、使用

    CSS Sprite简介: 利用CSS Sprites能很好地减少了网页的http请求次数,从而大大的提高了页面的性能,节省时间和带宽.CSS Sprites在国内很多人叫css精灵, 是一种网页图片 ...

  5. Laravel/php 一些调试技巧

    1. 模型属性不知道哪里修改? 直接覆盖模型的 setAttribute 方法,监测到某一个属性改动的时候,抛一个异常就可以看到堆栈了 use Illuminate\Database\Eloquent ...

  6. 关于HTML 5 canvas 的基础教程

    HTML 5 规范引进了很多新特性,其中最令人期待的之一就是 canvas 元素.HTML 5 canvas 提供了通过 JavaScript 绘制图形的方法,此方法使用简单但功能强大.每一个canv ...

  7. Vue双向数据绑定原理深度解析

    首先,什么是双向数据绑定?Vue是三大MVVM框架之一,数据绑定简单来说,就是当数据发生变化时,相应的视图会进行更新,当视图更新时,数据也会跟着变化. 在分析其原理和代码的时候,大家首先了解如下几个j ...

  8. 随笔记录 重置root密码 2019.8.7

    方法1:进入单用户模式 1.开机进入以下界面选择要启动的系统按e 2.找到星号行在后面添加上init=/bin/sh 3.按住Ctrl+x执行 4.进入单用户模式 5.如果passwd命令失败,可以直 ...

  9. 笔记36 Spring Web Flow——配置

    Spring Web Flow是一个Web框架,它适用于元素按规定流程运行的程序.Spring Web Flow是Spring MVC的扩展,它支持开发基于流程的应用程 序.它将流程的定义与实现流程行 ...

  10. Laravel Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found

    Laravel: 5.5.* 在迁移中有重命名操作的时候,运行 php artisan migrate 会提示 Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' ...