POJ3057 Evacuation(二分图最大匹配)
人作X部;把门按时间拆点,作Y部;如果某人能在某个时间到达某门则连边。就是个二分图最大匹配。
时间可以二分枚举,或者直接从1枚举时间然后加新边在原来的基础上进行增广。
谨记:时间是个不可忽视的维度。
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #include<algorithm>
- using namespace std;
- #define INF (1<<30)
- #define MAXN 80000
- #define MAXM 80000*400
- struct Edge{
- int v,cap,flow,next;
- }edge[MAXM];
- int vs,vt,NE,NV;
- int head[MAXN];
- void addEdge(int u,int v,int cap){
- edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=;
- edge[NE].next=head[u]; head[u]=NE++;
- edge[NE].v=u; edge[NE].cap=; edge[NE].flow=;
- edge[NE].next=head[v]; head[v]=NE++;
- }
- int level[MAXN];
- int gap[MAXN];
- void bfs(){
- memset(level,-,sizeof(level));
- memset(gap,,sizeof(gap));
- level[vt]=;
- gap[level[vt]]++;
- queue<int> que;
- que.push(vt);
- while(!que.empty()){
- int u=que.front(); que.pop();
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(level[v]!=-) continue;
- level[v]=level[u]+;
- gap[level[v]]++;
- que.push(v);
- }
- }
- }
- int pre[MAXN];
- int cur[MAXN];
- int ISAP(){
- bfs();
- memset(pre,-,sizeof(pre));
- memcpy(cur,head,sizeof(head));
- int u=pre[vs]=vs,flow=,aug=INF;
- gap[]=NV;
- while(level[vs]<NV){
- bool flag=false;
- for(int &i=cur[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(edge[i].cap!=edge[i].flow && level[u]==level[v]+){
- flag=true;
- pre[v]=u;
- u=v;
- //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
- aug=min(aug,edge[i].cap-edge[i].flow);
- if(v==vt){
- flow+=aug;
- for(u=pre[v]; v!=vs; v=u,u=pre[u]){
- edge[cur[u]].flow+=aug;
- edge[cur[u]^].flow-=aug;
- }
- //aug=-1;
- aug=INF;
- }
- break;
- }
- }
- if(flag) continue;
- int minlevel=NV;
- for(int i=head[u]; i!=-; i=edge[i].next){
- int v=edge[i].v;
- if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
- minlevel=level[v];
- cur[u]=i;
- }
- }
- if(--gap[level[u]]==) break;
- level[u]=minlevel+;
- gap[level[u]]++;
- u=pre[u];
- }
- return flow;
- }
- int n,m;
- char map[][];
- int d[][];
- bool vis[];
- int dx[]={,,,-};
- int dy[]={,-,,};
- void bfs(int x,int y){
- int s=x*m+y;
- queue<int> que;
- que.push(s);
- while(!que.empty()){
- x=que.front()/m; y=que.front()%m;
- for(int i=; i<; ++i){
- int nx=x+dx[i],ny=y+dy[i];
- if( nx<||nx>=n||ny<||ny>=m || map[nx][ny]!='.' || d[s][nx*m+ny] ) continue;
- d[s][nx*m+ny]=d[s][que.front()]+;
- vis[nx*m+ny]=;
- que.push(nx*m+ny);
- }
- que.pop();
- }
- }
- bool canEscape(){
- for(int i=; i<n; ++i){
- for(int j=; j<m; ++j){
- if(map[i][j]=='.' && !vis[i*m+j]) return ;
- }
- }
- return ;
- }
- int escape(int time){
- for(int i=; i<n; ++i){
- for(int j=; j<m; ++j){
- if(map[i][j]!='D') continue;
- addEdge(i*m+j+time*n*m,vt,);
- for(int x=; x<n; ++x){
- for(int y=; y<m; ++y){
- if(map[x][y]!='.') continue;
- if(d[i*m+j][x*m+y] && d[i*m+j][x*m+y]<=time+) addEdge(x*m+y,i*m+j+time*n*m,);
- }
- }
- }
- }
- return ISAP();
- }
- int main(){
- int t;
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&n,&m);
- for(int i=; i<n; ++i) scanf("%s",map[i]);
- memset(d,,sizeof(d));
- memset(vis,,sizeof(vis));
- for(int i=; i<n; ++i){
- for(int j=; j<m; ++j){
- if(map[i][j]=='D') bfs(i,j);
- }
- }
- if(!canEscape()){
- puts("impossible");
- continue;
- }
- vs=; vt=vs+; NV=vt+; NE=;
- memset(head,-,sizeof(head));
- int tot=;
- for(int i=; i<n; ++i){
- for(int j=; j<m; ++j){
- if(map[i][j]=='.') addEdge(vs,i*m+j,),++tot;
- }
- }
- int time=;
- while(tot){
- tot-=escape(time);
- ++time;
- }
- printf("%d\n",time);
- }
- }
POJ3057 Evacuation(二分图最大匹配)的更多相关文章
- POJ3057 Evacuation 二分图匹配+最短路
POJ3057 Evacuation 二分图匹配+最短路 题目描述 Fires can be disastrous, especially when a fire breaks out in a ro ...
- POJ Evacuation /// 二分图最大匹配
题目大意: 在一个n*m的房间中 ‘X’为墙 ‘D’为门 ‘.’为人 门只存在与外围 人每秒钟只能向四连通区域走一步 门比较狭窄 每秒钟只能通过一个人 求所有人逃脱的最短时间 如果不可能则输出impo ...
- POJ 2226二分图最大匹配
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...
- POJ2239 Selecting Courses(二分图最大匹配)
题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 #include <iostream ...
- poj 2239 二分图最大匹配,基础题
1.poj 2239 Selecting Courses 二分图最大匹配问题 2.总结:看到一个题解,直接用三维数组做的,很巧妙,很暴力.. 题意:N种课,给出时间,每种课在星期几的第几节课上 ...
- UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法
二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). ...
- 二分图最大匹配的König定理及其证明
二分图最大匹配的K?nig定理及其证明 本文将是这一系列里最短的一篇,因为我只打算把K?nig定理证了,其它的废话一概没有. 以下五个问题我可能会在以后的文章里说,如果你现在很想知道的话,网上 ...
- ZOJ1654 Place the Robots(二分图最大匹配)
最大匹配也叫最大边独立集,就是无向图中能取出两两不相邻的边的最大集合. 二分图最大匹配可以用最大流来解. 如果题目没有墙,那就是一道经典的二分图最大匹配问题: 把地图上的行和列分别作为点的X部和Y部, ...
- HDU:过山车(二分图最大匹配)
http://acm.hdu.edu.cn/showproblem.php?pid=2063 题意:有m个男,n个女,和 k 条边,求有多少对男女可以搭配. 思路:裸的二分图最大匹配,匈牙利算法. 枚 ...
随机推荐
- [BZOJ1061][Noi2008]志愿者招募
[BZOJ1061][Noi2008]志愿者招募 试题描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿 ...
- Step
php+MySQL html+css JQuery Mobile JavaScript weiPHP Sina Cloud 微信公众订阅号平台开发
- POJ 1017
http://poj.org/problem?id=1017 题意就是有6种规格的物品,给你一些不同规格的物品,要求你装在盒子里,盒子是固定尺寸的也就是6*6,而物品有1*1,2*2,3*3,4*4, ...
- jquery优势
1.轻量 2.开源 3.选择器出色 可以支持几乎 css1到css3 的所有选择器 4.简单的修改页面 不同的浏览器对于css的支持程度是不同的,jquery通过封装javascript的代码, ...
- c# 获取屏幕DPI
方法一:用ManagementClass来获取.需要引入System.Management.dll; using (ManagementClass mc = new ManagementClass(& ...
- BP神经网络模型与学习算法
一,什么是BP "BP(Back Propagation)网络是1986年由Rumelhart和McCelland为首的科学家小组提出,是一种按误差逆传播算法训练的多层前馈网络,是目前应用最 ...
- Linux C 单链表 读取文件 并排序 实例并解释
C的指针挺头疼的,先看一个例子: 给指针赋值和通过指针进行赋值这两种操作的差别确实让人费解.谨记区分的重要方法是:如果对左操作数进行解引用,则修改的是指针所指对象的值: 如果没有使用解引用操作, ...
- ubuntu下常用服务器的构建
1 ftp 1.1 ftp服务器 1.安装vsftpd服务器 sudo apt-get install vsftpd 2.配置vsftpd.conf文件 sudo vi /etc/vsftpd.con ...
- mysql-关于Unix时间戳(unix_timestamp)
unix_timestamp时间戳是自 1970 年 1 月 1 日(00:00:00 GMT)以来的秒数.它也被称为 Unix 时间戳(Unix Timestamp). Unix时间戳(Unix t ...
- 创建型模式之Strategy模式
应用场景 实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能.如编写排序算法,可以将这些算法写到一个类中,在该类中提供多个方法,每一个方法对应一个具体的 ...