题目大意:

在一个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. dubbo使用multicast注册方式消费者无法发现服务的一种情况(我遇到的情况)

    今天做dubbo测试的时候,翻出以前的代码,使用multicast广播地址的方式消费者居然无法发现服务.我的情况是因为启用了vmware虚拟机的网卡,导致了消费者无法发现服务,禁用vmware网卡后可 ...

  2. MVC3中_ViewStart.cshtml的一些事

    MVC3中,使用Razor模板引擎的话,会自动生成一个_ViewStart.cshtml文件. 很多人把这个文件当成类似Webform中的Master模板文件,其实这个_ViewStart.cshtm ...

  3. Codeforces 743C - Vladik and fractions (构造)

    Codeforces Round #384 (Div. 2) 题目链接:Vladik and fractions Vladik and Chloe decided to determine who o ...

  4. PXE装机

    支持 centOS 6 支持 PXE 装机的网卡必须自带 ROM(非意识性存储器)存储内容包括:DHCP 客户端,TFTP 客户端,PXE 协议客户端,将网卡设置第一启动项. DHCP:自动分配 IP ...

  5. 十、 shell基础

    shell的表现形式: history -c 清空历史命令(清空缓存;默认:1000条) -w 将缓存中的历史命令保存到配置文件中 ~/.bash_history 永久保存历史命令(默认:1000条) ...

  6. cm 安装cdh 后添加hive服务

    cm 安装cdh 后添加hive服务,出现错误提示 添加服务时候hive 配置如下: 错误信息提示: 错误日志: xec /opt/cloudera/parcels/CDH-5.4.7-1.cdh5. ...

  7. Spring IOC源码分析(一):ApplicationContext体系结构设计之自底向上分析

    spring-context包1. ApplicationContext接口 public interface ApplicationContext extends EnvironmentCapabl ...

  8. 屏幕操作录制成gif图的技巧

    我呢,在记录一些做过得实例的时候,总需要上一两张效果图,截静态图太浪费时间了,于是就找了一些录制git图的软件 一.Gif动画录制工具 这是我在360软件中心下载的,用了一下,不好用,录制出来的图是黑 ...

  9. Oracle中NEXTVAL 和 CURRVAL的使用

    能够通过在 SQL 语句中使用 NEXTVAL 或 CURRVAL 运算符来訪问序列的值.必须用以 sequence.NEXTVAL 或sequence.CURRVAL 格式驻留在同一个数据库中的序列 ...

  10. 覆盖element ui 的样式

    我们可以使用 !important  来覆盖element ui 的样式 首先先在浏览器中找到 我们所要修改的样式 ,然后找到她的 class  重新写他的样式 ,例如 . app  { width ...