POJ 3057 Evacuation(二分图匹配+BFS)

 

【题目链接】 http://poj.org/problem?id=3057

 

【题目大意】

  给出一个迷宫,D表示门,.表示人,X表示不可通行,
  每个门每时间单位只允许一个人通过,
  每个人移动一格的为一时间单位的时间,
  问所有人逃离这个迷宫的最小时间

 

【题解】

  我们首先对于每个门进行搜索,求出其到每个人的最短时间,
  之后我们将每扇门对于人来拆点,分别为这个人第几秒通过这个门
  将拆点后的门对所有人做一遍顺序二分图匹配
  匹配最终完成的时间的门是其第几个拆点那么时间就是第几秒

 

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector> 
#include <queue>
using namespace std;
const int MAX_V=10000;
int V,match[MAX_V];
vector<int> G[MAX_V];
bool used[MAX_V];
void add_edge(int u,int v){
    G[u].push_back(v);
    G[v].push_back(u);
}
bool dfs(int v){
    used[v]=1;
    for(int i=0;i<G[v].size();i++){
        int u=G[v][i],w=match[u];
        if(w<0||!used[w]&&dfs(w)){
            match[v]=u;
            match[u]=v;
            return 1;
        }
    }return 0;
}
const int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0};
const int MAX_X=12,MAX_Y=12;
int X,Y;
char field[MAX_X][MAX_X+1];
vector<int> dX,dY;
vector<int> pX,pY;
int dist[MAX_X][MAX_Y][MAX_X][MAX_Y];
void bfs(int x,int y,int d[MAX_X][MAX_Y]){
    queue<int> qx,qy;
    d[x][y]=0;
    qx.push(x);
    qy.push(y);
    while(!qx.empty()){
        x=qx.front(); qx.pop();
        y=qy.front(); qy.pop();
        for(int k=0;k<4;k++){
            int x2=x+dx[k],y2=y+dy[k];
            if(0<=x2&&x2<X&&0<=y2&&y2<Y&&field[x2][y2]=='.'&&d[x2][y2]<0){
                d[x2][y2]=d[x][y]+1;
                qx.push(x2);
                qy.push(y2);
            }
        }
    }
}
void solve(){
    int n=X*Y; 
    dX.clear(); dY.clear();
    pX.clear(); pY.clear();
    memset(dist,-1,sizeof(dist));
    for(int x=0;x<X;x++){
        for(int y=0;y<Y;y++){
            if(field[x][y]=='D'){
                dX.push_back(x);
                dY.push_back(y);
                bfs(x,y,dist[x][y]);
            }else if(field[x][y]=='.'){
                pX.push_back(x);
                pY.push_back(y);
            }
        }
    }
    int d=dX.size(),p=pX.size();
    for(int i=0;i<=n*d+p;i++)G[i].clear();
    for(int i=0;i<d;i++){
        for(int j=0;j<p;j++){
            if(dist[dX[i]][dY[i]][pX[j]][pY[j]]>=0){
                for(int k=dist[dX[i]][dY[i]][pX[j]][pY[j]];k<=n;k++){
                   add_edge((k-1)*d+i,n*d+j);
                }
            }
        }
    }
    if(p==0){
        puts("0");
        return;
    }
    int num=0;
    memset(match,-1,sizeof(match));
    for(int v=0;v<n*d;v++){
        memset(used,0,sizeof(used));
        if(dfs(v)){
            if(++num==p){
                printf("%d\n",v/d+1);
                return;
            }
        }
    }puts("impossible");
}
int T;
void init(){
    scanf("%d%d",&X,&Y);
    for(int i=0;i<X;i++)scanf("%s",field[i]);
}
int main(){
    scanf("%d",&T);
    while(T--){
        init();
        solve();
    }return 0;
}
posted @ 2017-02-09 13:49  forever97  阅读(197)  评论(0编辑  收藏  举报