結果

問題 No.1467 Selling Cars
ユーザー kimiyukikimiyuki
提出日時 2021-04-02 23:39:00
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
TLE  
実行時間 -
コード長 5,985 bytes
コンパイル時間 2,676 ms
コンパイル使用メモリ 223,504 KB
実行使用メモリ 15,488 KB
最終ジャッジ日時 2024-06-06 08:41:41
合計ジャッジ時間 13,059 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 TLE -
testcase_01 -- -
testcase_02 -- -
testcase_03 -- -
testcase_04 -- -
testcase_05 -- -
testcase_06 -- -
testcase_07 -- -
testcase_08 -- -
testcase_09 -- -
testcase_10 -- -
testcase_11 -- -
testcase_12 -- -
testcase_13 -- -
testcase_14 -- -
testcase_15 -- -
testcase_16 -- -
testcase_17 -- -
testcase_18 -- -
testcase_19 -- -
testcase_20 -- -
testcase_21 -- -
testcase_22 -- -
testcase_23 -- -
testcase_24 -- -
testcase_25 -- -
testcase_26 -- -
testcase_27 -- -
testcase_28 -- -
testcase_29 -- -
testcase_30 -- -
testcase_31 -- -
testcase_32 -- -
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 1 "main.cpp"
#include <bits/stdc++.h>
#line 2 "/home/user/Library/utils/macros.hpp"
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) std::begin(x), std::end(x)
#line 7 "/home/user/Library/graph/minimum-cost-flow.hpp"

namespace min_cost_flow {

template <class T>
struct edge { int to; T cap, cost; int rev; };

template <class T>
void add_edge(std::vector<std::vector<edge<T> > > & graph, int from, int to, T cap, T cost) {
    graph[from].push_back((edge<T>) {   to, cap,  cost, int(graph[  to].size())     });
    graph[  to].push_back((edge<T>) { from,  0, - cost, int(graph[from].size()) - 1 });
}

template <class T>
using reversed_priority_queue = std::priority_queue<T, std::vector<T>, std::greater<T> >;

/**
 * @brief 最小費用流 (primal-dual)
 * @note mainly $O(V^2 U C)$ for U is the sum of capacities and $C$ is the sum of costs. and additional $O(V E)$ if negative edges exist
 */
template <class T>
T run_destructive(std::vector<std::vector<edge<T> > > & graph, int src, int dst, T flow) {

    T result = 0;
    std::vector<T> potential(graph.size());
    if (0 < flow) {  // initialize potential when negative edges exist (slow). you can remove this if unnecessary
        std::fill(ALL(potential), std::numeric_limits<T>::max());
        potential[src] = 0;
        while (true) {  // Bellman-Ford algorithm
            bool updated = false;
            REP (e_from, graph.size()) for (auto & e : graph[e_from]) if (e.cap) {
                if (potential[e_from] == std::numeric_limits<T>::max()) continue;
                if (potential[e.to] > potential[e_from] + e.cost) {
                    potential[e.to] = potential[e_from] + e.cost;  // min
                    updated = true;
                }
            }
            if (not updated) break;
        }
    }

    while (0 < flow) {
        // update potential using dijkstra
        std::vector<T> distance(graph.size(), std::numeric_limits<T>::max());  // minimum distance
        std::vector<int> prev_v(graph.size());  // constitute a single-linked-list represents the flow-path
        std::vector<int> prev_e(graph.size());
        {  // initialize distance and prev_{v,e}
            reversed_priority_queue<std::pair<T, int> > que;  // distance * vertex
            distance[src] = 0;
            que.emplace(0, src);
            while (not que.empty()) {  // Dijkstra's algorithm
                T d; int v; std::tie(d, v) = que.top(); que.pop();
                if (potential[v] == std::numeric_limits<T>::max()) continue;  // for unreachable nodes
                if (distance[v] < d) continue;
                // look round the vertex
                REP (e_index, graph[v].size()) {
                    // consider updating
                    edge<T> e = graph[v][e_index];
                    int w = e.to;
                    if (potential[w] == std::numeric_limits<T>::max()) continue;
                    T d1 = distance[v] + e.cost + potential[v] - potential[w];  // updated distance
                    if (0 < e.cap and d1 < distance[e.to]) {
                        distance[w] = d1;
                        prev_v[w] = v;
                        prev_e[w] = e_index;
                        que.emplace(d1, w);
                    }
                }
            }
        }
        if (distance[dst] == std::numeric_limits<T>::max()) return -1;  // no such flow
        REP (v, graph.size()) {
            if (potential[v] == std::numeric_limits<T>::max()) continue;
            potential[v] += distance[v];
        }

        // finish updating the potential
        // let flow on the src->dst minimum path
        T delta = flow; // capacity of the path
        for (int v = dst; v != src; v = prev_v[v]) {
            delta = std::min(delta, graph[prev_v[v]][prev_e[v]].cap);
        }
        flow -= delta;
        result += delta * potential[dst];
        for (int v = dst; v != src; v = prev_v[v]) {
            edge<T> & e = graph[prev_v[v]][prev_e[v]];  // reference
            e.cap -= delta;
            graph[v][e.rev].cap += delta;
        }
    }
    return result;
}

}
#line 4 "main.cpp"
using namespace std;

vector<int64_t> solve(int m, int n, const vector<int64_t>& a, const vector<int64_t>& b) {
    // coordinate compression
    vector<int> points;
    points.insert(points.end(), ALL(a));
    points.insert(points.end(), ALL(b));
    sort(ALL(points));
    points.erase(unique(ALL(points)), points.end());
    auto lookup = [&](int x) -> int {
        return lower_bound(ALL(points), x) - points.begin();
    };

    int src = points.size();
    int dst = points.size() + 1;

    vector<int64_t> ans(m);
    REP (k, m) {
        std::vector<std::vector<min_cost_flow::edge<int64_t> > > g(points.size() + 2);
        REP (i, m) {
            min_cost_flow::add_edge<int64_t>(g, src, lookup(a[i]), 1, 0);
        }
        REP (i, (int)points.size() - 1) {
            int64_t delta = points[i + 1] - points[i];
            min_cost_flow::add_edge<int64_t>(g, i, i + 1, m, delta);
            min_cost_flow::add_edge<int64_t>(g, i + 1, i, m, delta);
        }
        REP (j, n) {
            min_cost_flow::add_edge<int64_t>(g, lookup(b[j]), dst, k + 1, 0);
        }
        ans[k] = min_cost_flow::run_destructive<int64_t>(g, src, dst, m);
    }
    return ans;
}

// generated by oj-template v4.7.2 (https://github.com/online-judge-tools/template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    int M, N;
    cin >> M;
    vector<int64_t> A(M);
    cin >> N;
    vector<int64_t> B(N);
    REP (i, M) { cin >> A[i]; }
    REP (i, N) { cin >> B[i]; }
    auto ans = solve(M, N, A, B);
    REP (i, M) { cout << ans[i] << endl; }
    return 0;
}
0