QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#84102#5664. Printing Stickerssugim48Compile Error//C++176.7kb2023-03-05 14:54:052023-03-05 14:54:08

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-03-05 14:54:08]
  • 评测
  • [2023-03-05 14:54:05]
  • 提交

answer

#include <bits/stdc++.h>
#include <atcoder/maxflow>
using namespace std;
using namespace atcoder;

#define rep(i, N) for (int i = 0; (i) < (int)(N); (i)++)
#define all(x) begin(x), end(x)
#define pb push_back

using ll = long long;
using i_i = tuple<int, int>;

const int INF = INT_MAX / 10;

struct Edge { int u, v, w; };

struct union_find {
    vector<int> v;
    union_find(int n) : v(n, -1) {}
    int find(int x) { return v[x] < 0 ? x : v[x] = find(v[x]); }
    void unite(int x, int y) {
        x = find(x); y = find(y);
        if (x == y) return;
        if (-v[x] < -v[y]) swap(x, y);
        v[x] += v[y]; v[y] = x;
    }
    bool root(int x) { return v[x] < 0; }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return -v[find(x)]; }
};

vector<int> solve(int N, int M, int H, int V, vector<string> slash, vector<vector<bool>> black, vector<vector<int>> cost) {
    auto f = [&](int i, int j, int z) -> int {
        if (0 <= i && i < N && 0 <= j && j < M)
            return (i * M + j) * 2 + z;
        return -1;
    };

    auto is_black = [&](int u) -> bool {
        return u != -1 && black[u / (M * 2)][u % (M * 2)];
    };

    vector<Edge> E;

    auto add_edge = [&](int i1, int j1, int z1, int i2, int j2, int z2, int w) {
        int u = f(i1, j1, z1);
        int v = f(i2, j2, z2);
        if (is_black(u) || is_black(v)) w = INF;
        E.pb(Edge{u, v, w});
    };

    // vertical
    rep(i, N) rep(j, M + 1) {
        add_edge(i, j - 1, 1, i, j, 0, V);
    }
    // horizontal
    rep(j, M) rep(i, N + 1) {
        int z1 = (i - 1 >= 0 && slash[i - 1][j] == '\\') ? 0 : 1;
        int z2 = (i < N && slash[i][j] == '/') ? 0 : 1;
        add_edge(i - 1, j, z1, i, j, z2, H);
    }
    // diagonal
    rep(i, N) rep(j, M) {
        add_edge(i, j, 0, i, j, 1, cost[i][j]);
    }
    int L = E.size();

    union_find uf(N * M * 2);
    rep(i, N + 1) rep(j, M + 1) {
        vector<int> vs;
        // upper left
        if (i - 1 >= 0 && j - 1 >= 0) {
            vs.pb(f(i - 1, j - 1, 1));
            if (slash[i - 1][j - 1] == '\\') {
                vs.pb(f(i - 1, j - 1, 0));
            }
        }
        // upper right
        if (i - 1 >= 0 && j < M) {
            vs.pb(f(i - 1, j, 0));
            if (slash[i - 1][j] == '/') {
                vs.pb(f(i - 1, j, 1));
            }
        }
        // lower left
        if (i < N && j - 1 >= 0) {
            vs.pb(f(i, j - 1, 1));
            if (slash[i][j - 1] == '/') {
                vs.pb(f(i, j - 1, 0));
            }
        }
        // lower right
        if (i < N && j < M) {
            vs.pb(f(i, j, 0));
            if (slash[i][j] == '\\') {
                vs.pb(f(i, j, 1));
            }
        }
        vector<int> _vs;
        for (int u: vs) if (is_black(u)) _vs.pb(u);
        vs = _vs;
        int K = vs.size();
        for (int k = 0; k + 1 < K; k++)
            uf.unite(vs[k], vs[k + 1]);
    }

    vector<vector<int>> components(N * M * 2);
    rep(u, N * M * 2) if (is_black(u)) components[uf.find(u)].pb(u);
    vector<vector<int>> _components;
    for (auto vs: components) if (!vs.empty()) _components.pb(vs);
    components = _components;
    int C = components.size();

    vector<bool> cut(L);
    rep(l, L) if (E[l].u == -1 || E[l].v == -1) cut[l] = true;

    rep(bit, 10) {
        mf_graph<int> G(N * M * 2 + 2);
        int s = N * M * 2;
        int t = N * M * 2 + 1;
        rep(l, L) if (!cut[l]) {
            G.add_edge(E[l].u, E[l].v, E[l].w);
            G.add_edge(E[l].v, E[l].u, E[l].w);
        }
        rep(c, C) {
            auto vs = components[c];
            for (int u: vs) {
                if (c>>bit & 1) G.add_edge(s, u, INF);
                else G.add_edge(u, t, INF);
            }
        }
        G.flow(s, t);
        vector<bool> reach = G.min_cut(s);
        rep(l, L) if ((E[l].u != -1 && reach[E[l].u]) ^ (E[l].v != -1 && reach[E[l].v])) cut[l] = true;
    }

    {
        mf_graph<int> G(N * M * 2 + C + 2);
        int s = N * M * 2;
        int t = N * M * 2 + 1;
        rep(l, L) {
            if (cut[l]) {
                if (E[l].u != -1) G.add_edge(E[l].u, t, E[l].w);
                if (E[l].v != -1) G.add_edge(E[l].v, t, E[l].w);
            } else {
                G.add_edge(E[l].u, E[l].v, E[l].w);
                G.add_edge(E[l].v, E[l].u, E[l].w);
            }
        }
        rep(c, C) {
            auto vs = components[c];
            for (int u: vs) G.add_edge(s, u, INF);
        }

        G.flow(s, t);
        vector<bool> reach = G.min_cut(s);
        rep(l, L) if ((E[l].u != -1 && reach[E[l].u]) ^ (E[l].v != -1 && reach[E[l].v])) cut[l] = true;
    }

    vector<int> ans(C);
    {
        vector<vector<int>> G(N * M * 2);
        vector<int> unko(N * M * 2);
        rep(l, L) {
            Edge e = E[l];
            if (cut[l]) {
                if (e.u != -1) unko[e.u] += e.w;
                if (e.v != -1) unko[e.v] += e.w;
            } else {
                G[e.u].pb(e.v);
                G[e.v].pb(e.u);
            }
        }

        vector<bool> vis(N * M * 2);

        auto dfs = [&](auto self, int u, int c) {
            if (vis[u]) return;
            vis[u] = true;
            ans[c] += unko[u];
            unko[u] = 0;
            for (int v: G[u]) self(self, v, c);
        };

        rep(c, C) {
            auto vs = components[c];
            for (int u: vs) dfs(dfs, u, c);
        }
    }

    sort(all(ans));
    return ans;
}

int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

//    rep(t, 50) {
//        int N = 100;
//        int M = 100;
//        int H = 1000;
//        int V = 1000;
//        vector<string> slash(N, string(M, '/'));
//        vector<vector<bool>> black(N, vector<bool>(M * 2));
//        rep(i, 32) rep(j, 32) black[i * 3][j * 3 * 2] = true;
//        vector<vector<int>> cost(N, vector<int>(M, rand() % 1000 + 1));
//        solve(N, M, H, V, slash, black, cost);
//    }

    int T; cin >> T;
    while (T--) {
        int N, M, H, V;
        cin >> N >> M >> H >> V;
        vector<string> slash(N);
        rep(i, N) cin >> slash[i];
        vector<vector<bool>> black(N, vector<bool>(M * 2));
        rep(i, N) {
            string s; cin >> s;
            rep(j, M * 2) black[i][j] = (s[j] == '#');
        }
        vector<vector<int>> cost(N, vector<int>(M));
        rep(i, N) rep(j, M) cin >> cost[i][j];
        auto ans = solve(N, M, H, V, slash, black, cost);
        int K = ans.size();
        cout << K << '\n';
        rep(k, K) cout << ans[k] << (k + 1 < K ? ' ' : '\n');
    }
}

Details

answer.code:2:10: fatal error: atcoder/maxflow: No such file or directory
    2 | #include <atcoder/maxflow>
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.