• 【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
    ", k );
        }
        return 0;
    }
    /*
    5 5
    XXXXX
    X...D
    XX.XX
    X..XX
    XXDXX
    */
  • 相关阅读:
    把你的名字刻到IE上
    C#格式化字符串
    CEO、COO、CFO、CTO、CIO
    Net通用分页(可以选择页码的显示,且有中英选择)
    laravelmiddleware中间件常用使用方法
    laravel路由组中namespace的的用法详解
    qq自己设定动态图像视屏
    laravel实现excel表的导入导出功能
    git创建远程分支并推送
    jquery如何用Ajax将信息遍历到界面上
  • 原文地址:https://www.cnblogs.com/cocottt/p/6764976.html
Copyright © 2020-2023  润新知