POJ 3057 Evacuation (二分图 ,)

题意

  • 在一个用矩阵描述的房间里,每个非墙位置都有一个人
  • 矩阵外侧一圈,是墙或者门
  • 每个人移动一格的时间为1,但是每个时刻通过门的人数只能为1
  • 问你最快所有人出房间的时间为多少

思路:

首先我们要 bfs 一遍,以每个门为起点,找人到门的最短距离,

然后我们不断增加时间,每个时间我们增加 门 的数量,增加的数量就是门的总数,然后在这个时间内可以逃脱的人向门连一条边,然后我们进行二分图匹配。如果得出的结果跟人数一样,那么这个时间就是最小时间,否则,我们在重复之前的操作。

知道最大匹配得出的结果和人数一样为止。

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
#define X first
#define Y second
#define mem(x,v) memset(x,v,sizeof(x))
typedef pair<int,int> P;
const int dx[4] = {-1,1,0,0};
const int dy[4] = {0,0,-1,1};
const int INF = 0x3f3f3f3f;
int dis[20][20][20][20];
int n,m,t,dl,pl;
bool used[50000],vv[20][20];
char ma[20][20];
vector<P>d,p;
vector<int> f[50000];
int linker[50000];
void bfs(int u, int v){
    int x,y;
    dis[u][v][u][v] = 0;
    queue<P>que;
    que.push(P(u,v));
    while(!que.empty()) {
        P uq = que.front(); que.pop();
        int s = uq.X, t = uq.Y;
        for (int i = 0; i < 4; i++) {
            x = s + dx[i];
            y = t + dy[i];
            if (ma[x][y] == '.' && x >= 0 && x < n && y >= 0 && y < m && dis[u][v][x][y] > dis[u][v][s][t] + 1){
                dis[u][v][x][y] = dis[u][v][s][t] + 1;
                vv[x][y]= 1;
                que.push(P(x,y));
            }
        }
    }
}
bool dfs(int u){
    for (int i = 0; i < f[u].size(); i++){
        if (!used[f[u][i]]){
            used[f[u][i]] = 1;
            if (linker[f[u][i]] == -1 || dfs(linker[f[u][i]])){
                linker[f[u][i]] = u;
                return 1;
            }
        }
    }
    return 0;
}
int main() {
    int T;
    cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);
        for (int i = 0; i < n; i++)
            cin>>ma[i];
        d.clear(); p.clear();
        mem(vv,0);
        mem(dis,INF);
        mem(linker,-1);
        dl = 0,pl = 0;
        for (int i = 0; i < n; i++){
            for (int j = 0; j < m; j++){
                if (ma[i][j] == 'D'){
                    d.push_back(P(i,j));
                    dl++;
                    bfs(i,j);
                }
                if (ma[i][j] == '.') p.push_back(P(i,j)),pl++;
            }
        }
   /*     for (int i = 0; i < n; i++){
            for (int j = 0; j < m; j++)
                printf("%d ",dis[d[0].X][d[0].Y][i][j]);
            printf("\n");
        } */
        bool flag = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (ma[i][j] == '.' && vv[i][j] == 0){
                    flag = 1;
                    break;
                }
        if (flag){
            printf("impossible\n");
            continue;
        }
        for (int i = 0; i < 40000; i ++)
            f[i].clear();
        t = 0;
        int ans = 0;
        for ( ; ; ){
            for (int i = 0; i < dl; i++)
                for (int j = 0; j < pl; j++)
                    if (dis[d[i].X][d[i].Y][p[j].X][p[j].Y] <= t + 1) f[t * dl + i].push_back(p[j].X*m+p[j].Y);
            t++;
            for (int i = (t-1)*dl; i < t * dl; i++){
                mem(used,0);
                if (dfs(i)) ans++;
            }
            if (ans >= pl) break;
        }
        printf("%d\n",t);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/kidsummer/article/details/81261009