萌新刚学算法,70 分求调
查看原帖
萌新刚学算法,70 分求调
440870
油炸皮卡丘0vo楼主2022/8/27 10:18

没有将门进行拆点,而是将门向时间连边,点集就是汇源点+人+门+二分的时间,但是wa了最后三个点,不知道哪错了qwq

#include<bits/stdc++.h>
using LL = long long;

constexpr int INF = 0x3f3f3f3f;
template< typename T >
struct Edge {
    int from, to;
    T cap, flow;

    Edge(int u, int v, T c, T f) : from(u), to(v), cap(c), flow(f) {}
};
template< typename T >
struct Dinic {
    int n, m;
    int Source, Sink;
    std::vector< Edge< T > > edges;
    std::vector< std::vector< int > > G;
    std::vector< int > d, cur;
    std::vector< bool > vis;

    // number of vertices
    Dinic(int n) : n(n), d(n), cur(n), vis(n), G(n) {}
    
    void AddEdge(int from, int to, T cap) {
        edges.push_back(Edge< T >(from, to, cap, 0));
        edges.push_back(Edge< T >(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    }

    bool BFS() {
        vis.assign(n, 0);
        std::queue< int > Q;
        Q.push(Source);
        d[Sink] = 0;
        vis[Source] = true;
        while (!Q.empty()) {
            int x = Q.front();
            Q.pop();
            for (int i = 0; i < G[x].size(); ++ i) {
                Edge< T > &e = edges[G[x][i]];
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = true;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[Sink];
    }

    T DFS(int x, T a) {
        if (x == Sink || a == 0) {
            return a;
        }
        T flow = 0, f;
        for (int& i = cur[x]; i < G[x].size(); ++ i) {
            Edge< T > &e = edges[G[x][i]];
            if (d[x] + 1 == d[e.to] && (f = DFS(e.to, std::min(a, e.cap - e.flow))) > 0) {
                e.flow += f;
                edges[G[x][i] ^ 1].flow -= f;
                flow += f;
                a -= f;
                if (a == 0) {
                    break;
                }
            }
        }
        return flow;
    }

    T Maxflow(int s, int t) {
        this->Source = s;
        this->Sink = t;
        T flow = 0;
        while (BFS()) {
            cur.assign(n, 0);
            flow += DFS(Source, INF);
        }
        return flow;
    }
};
struct Node {
    int x, y, step;
};
struct Point {
    int x, y;
};
const int N = 25;
int n, m, dis[N][N][N][N];
char s[N][N];
std::vector< Point > start, end;
bool vis[N][N];
std::vector< std::pair< int, int > > go {
    {1, 0}, {-1, 0},
    {0, 1}, {0, -1}
};
int BFS(int x1, int y1, int x2, int y2) {
    memset(vis, false, sizeof vis);
    vis[x1][y1] = true;
    std::queue< Node > q;
    q.push({x1, y1, 0});
    while (!q.empty()) {
        Node p = q.front();
        q.pop();
        if (p.x == x2 && p.y == y2) {
            return p.step;
        }
        for (auto &[i, j] : go) {
            int nx = p.x + i, ny = p.y + j;
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny]) {
                vis[nx][ny] = true;
                q.push({nx, ny, p.step + 1});
            } 
        }
    }
    return INF;
}
bool check(int mid) {
    int x = start.size(), y = end.size();
    Dinic< int > F(x + y + mid + 2);
    int s = x + y + mid, t = s + 1;
    for (int i = 0; i < x; ++ i) {
        F.AddEdge(s, i, 1);
    }
    for (int i = 0; i < mid; ++ i) {
        F.AddEdge(x + y + i, t, INF);
    }
    for (int i = 0; i < y; ++ i) {
        for (int j = 0; j < mid; ++ j) {
            F.AddEdge(x + i, x + y + j, 1);
        }
    }
    for (int i = 0; i < x; ++ i) {
        for (int j = 0; j < y; ++ j) {
            if (dis[start[i].x][start[i].y][end[j].x][end[j].y] <= mid) {
                F.AddEdge(i, x + j, 1);
            }
        }
    }
    return F.Maxflow(s, t) == x;
}
signed main() {
    #ifndef ONLINE_JUDGE
    freopen("Input.txt", "r", stdin);
    freopen("Output.txt", "w", stdout);
    #endif

    scanf("%d %d", &n, &m);
    for (int i = 0; i < n; ++ i) {
        scanf("%s", s[i]);
        for (int j = 0; j < m; ++ j) {
            if (s[i][j] == '.') {
                start.push_back({i, j});
            } else if (s[i][j] == 'D') {
                end.push_back({i, j});
            }
        }
    }
    for (auto &[x1, y1] : start) {
        for (auto &[x2, y2] : end) {
            dis[x1][y1][x2][y2] = BFS(x1, y1, x2, y2);
        }
    }
    int l = 1, r = 1000, ans = -1;
    while (l <= r) {
        int mid = (l + r) / 2;
        if (check(mid)) {
            r = mid - 1;
            ans = mid;
        } else {
            l = mid + 1;
        }
    }
    if (ans != -1) {
        printf("%d\n", ans);
    } else {
        puts("impossible");
    }
    return 0;
}
2022/8/27 10:18
加载中...