【bzoj1189】[HNOI2007]紧急疏散evacuate

来源:互联网 发布:经济型酒店数据分析 编辑:程序博客网 时间:2024/03/29 14:37

*题目描述:
发生了火警,所有人员需要紧急疏散!假设每个房间是一个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 secondchar 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 1000010struct 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 5XXXXXX...DXX.XXX..XXXXDXX*/
0 0
原创粉丝点击