题目大意:

在一个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. Retrofit全攻略——进阶篇

    最近事比较多,距离上次写文章已经过去了一个月了.上一篇文章Retrofit全攻略——基础篇 介绍了Retrofit的基础用法,这篇文章介绍点进阶的用法. 打印网络日志 在开发阶段,为了方便调试,我们需 ...

  2. Jeecg集成Swagger-ui

    <context:component-scan base-package="springfox"/> <bean class="org.jeecgfra ...

  3. testNG官方文档翻译-1 简介

    官方文档链接http://testng.org/doc/documentation-main.html 简介 TestNG是一个被设计用来简化广泛的测试需求的测试框架,它既可应用于单元测试(测试一个独 ...

  4. Java中的注解是如何工作的?

    自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...

  5. Nginx学习——简介及常用命令

    Nginx简介 Nginx是什么 同Apache一样,都是一种WEB服务器 基于REST架构风格,以统一资源描述符(URI)或者统一资源定位符(URL)作为沟通依据,通过HTTP协议提供各种网络服务 ...

  6. 高效IO之Dex加密(三)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 apk加固原理之dex加密 原理其实不复杂,加固其实就是加密dex文件,防止de ...

  7. Vue之自建管理后台(二)Vue端设计

    我们先设计Vue的文件夹分布. 在此之前,我们先了解下初始化创建的Vue的文件夹 https://www.cnblogs.com/luoxuemei/p/9812151.html (我引用了这哥们写的 ...

  8. 从身份证号提取生日并更新到生日字段中的SQL语句

    1:根据身份证号 更新 生日字段 SQL update 学生信息 ,)+,)+,) 2:根据身份证号 更新 性别字段 SQL update 学生信息 set 性别='男' and substring( ...

  9. Linux(二)高级文本处理

    一.cut (cut 命令可以从一个文本文件或者文本流中提取文本列 ) 1.cut语法 cut -d '分隔字符' -f fields         用于有特定分隔字符 cut  -c 字符区间   ...

  10. 代码格式化工具---prettier配置

    我自己的常用 prettier 配置如下: // .prettierrc 文件 // 这里修改的都是与默认值不同的,没有修改到的就是启用默认值 // .prettierrc 文件是使用 json 格式 ...