【bzoj1189】[HNOI2007]紧急疏散evacuate

*题目描述:
发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是’.’,那么表示这是一块空地;如果是’X’,那么表示这是一面墙,如果是’D’,那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

*输入:
输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符’.’、’X’和’D’,且字符间无空格。

*输出:
只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出’impossible’(不包括引号)。

*样例输入:
5 5
XXXXX
X…D
XX.XX
X..XX
XXDXX

*样例输出:
3

*题解:
bfs+枚举答案网络流判定。
先把每个点到每个门的最短距离用bfs求出来,然后建分层图来跑网络流,直到最大流为点数时就是答案。

*代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>

#ifdef WIN32
    #define LL "%I64d"
#else
    #define LL "%lld"
#endif

#ifdef CT
    #define debug(...) printf(__VA_ARGS__)
    #define setfile() 
#else
    #define debug(...)
    #define filename ""
    #define setfile() freopen(filename".in", "r", stdin); freopen(filename".out", "w", stdout)
#endif

#define R register
#define getc() (S == T && (T = (S = B) + fread(B, 1, 1 << 15, stdin), S == T) ? EOF : *S++)
#define dmax(_a, _b) ((_a) > (_b) ? (_a) : (_b))
#define dmin(_a, _b) ((_a) < (_b) ? (_a) : (_b))
#define cmax(_a, _b) (_a < (_b) ? _a = (_b) : 0)
#define cmin(_a, _b) (_a > (_b) ? _a = (_b) : 0)
#define cabs(_x) ((_x) < 0 ? (- (_x)) : (_x))
char B[1 << 15], *S = B, *T = B;
inline int F()
{
    R char ch; R int cnt = 0; R bool minus = 0;
    while (ch = getc(), (ch < '0' || ch > '9') && ch != '-') ;
    ch == '-' ? minus = 1 : cnt = ch - '0';
    while (ch = getc(), ch >= '0' && ch <= '9') cnt = cnt * 10 + ch - '0';
    return minus ? -cnt : cnt;
}
#define maxn 30
#define P std::pair<int, int>
#define mkp std::make_pair
#define fir first
#define sec second
char str[maxn][maxn];
int id[maxn][maxn], dis[maxn * maxn][maxn * maxn],  n, m;
const int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
P door[maxn * maxn], p[maxn * maxn];
struct Queue
{
    int x, y, step;
}q2[maxn * maxn * 10];
bool vis[maxn][maxn];
inline void bfs(R int x, R int y, R int now)
{
    memset(vis, 0, sizeof (vis));
    memset(dis[now], 63, sizeof (dis[now]));
    R int head = 0, tail = 1;
    q2[1] = (Queue) {x, y, 0};
    R bool flag = 1;
    while (head < tail)
    {
        ++head;
        for (R int i = 0; i < 4; ++i)
        {
            R int nx = q2[head].x + dx[i], ny = q2[head].y + dy[i];
            if (nx && ny && nx <= n && ny <= m && !vis[nx][ny])
            {
                vis[nx][ny] = 1;
                if (str[nx][ny] == 'D') dis[now][id[nx][ny]] = q2[head].step + 1, flag = 0;
                else if (str[nx][ny] == '.')
                {
                    q2[++tail] = (Queue) {nx, ny, q2[head].step + 1};
                }
            }
        }
    }
    if (flag) {puts("impossible");exit(0);}
}

#define maxp 10010
#define maxm 1000010
struct Edge
{
    Edge *next, *rev;
    int to, cap;
}*last[maxp], *cur[maxp], e[maxm], *ecnt = e;
int dep[maxp], s, t, ans;
std::queue<int> q;
inline void link(R int a, R int b, R int w)
{
    *++ecnt = (Edge) {last[a], ecnt + 1, b, w}; last[a] = ecnt;
    *++ecnt = (Edge) {last[b], ecnt - 1, a, 0}; last[b] = ecnt;
}
inline bool bfs()
{
    memset(dep, -1, sizeof (dep));
    q.push(t); dep[t] = 0;
    while (!q.empty())
    {
        R int now = q.front(); q.pop();
        for (R Edge *iter = last[now]; iter; iter = iter -> next)
        {
            R int pre = iter -> to;
            if (iter -> rev -> cap && dep[pre] == -1)
            {
                dep[pre] = dep[now] + 1;
                q.push(pre);
            }
        }
    }
    return dep[s] != -1;
}
int dfs(R int x, R int f)
{
    if (x == t) return f;
    R int used = 0;
    for (R Edge* &iter = cur[x]; iter; iter = iter -> next)
    {
        R int pre = iter -> to;
        if (iter -> cap && dep[x] == dep[pre] + 1)
        {
            R int v = dfs(pre, dmin(iter -> cap, f - used));
            iter -> cap -= v;
            iter -> rev -> cap += v;
            used += v;
            if (used == f) return f;
        }
    }
    if (!used) dep[x] = -1;
    return used;
}
inline void dinic()
{
    while (bfs())
    {
        memcpy(cur, last, sizeof last);
        ans += dfs(s, 0x7fffffff);
    }
}
int main()
{
//  setfile();
    scanf("%d%d", &n, &m);
    R int pcnt = 0, dcnt = 0;
    for (R int i = 1; i <= n; ++i)
        scanf("%s", str[i] + 1);
    for (R int i = 1; i <= n; ++i)
        for (R int j = 1; j <= m; ++j)
            if (str[i][j] == 'D')
                door[++dcnt] = mkp(i, j), id[i][j] = dcnt;
            else if (str[i][j] == '.') p[++pcnt] = mkp(i, j);
    for (R int i = 1; i <= pcnt; ++i)
        bfs(p[i].fir, p[i].sec, i);
    R int cnt = pcnt;
    s = 0; t = maxp - 2;
    for (R int i = 1; i <= pcnt; ++i) link(s, i, 1);
    for (R int k = 1; ; ++k)
    {
        for (R int i = 1; i <= dcnt; ++i)
        {
            ++cnt;
            link(cnt, t, 1);
            for (R int j = 1; j <= pcnt; ++j)
                if (dis[j][i] <= k)
                    link(j, cnt, 1);
        }
        dinic();
        if (ans == pcnt) return !printf("%d\n", k );
    }
    return 0;
}
/*
5 5
XXXXX
X...D
XX.XX
X..XX
XXDXX
*/
posted @ 2016-09-21 17:28  cot  阅读(220)  评论(0编辑  收藏  举报