제출 #714451

#제출 시각아이디문제언어결과실행 시간메모리
714451pashkaPotatoes and fertilizers (LMIO19_bulves)C++14
0 / 100
1067 ms1400 KiB
#include <bits/stdc++.h>

#define long long long int
#define DEBUG
using namespace std;

// @author: pashka

struct mincost {

    const long INF = 1e18;

    struct edge {
        int src, dst, maxCap, cost, flw, cap;
    };

    vector<edge> edges;
    vector<vector<int>> graph;

    vector<long> phi;

    void dijkstra(int s, vector<long> &d, vector<int> &prev) {
        std::fill(d.begin(), d.end(), INF);
        d[s] = 0;
        std::priority_queue<pair<long, int>> pq;
        pq.push({-d[s], s});
        while (!pq.empty()) {
            int v = pq.top().second;
            long cur_d = -pq.top().first;
            pq.pop();
            if (cur_d > d[v]) continue;
            for (int j = 0; j < graph[v].size(); ++j) {
                edge &e = edges[graph[v][j]];
                if (e.flw == e.cap) continue;
                long dd = d[v] + e.cost + phi[e.src] - phi[e.dst];
                if (dd < d[e.dst]) {
                    d[e.dst] = dd;
                    prev[e.dst] = graph[v][j];
                    pq.push({-d[e.dst], e.dst});
                }
            }
        }
    }

    void init(int n) {
        graph.resize(n);
        phi.resize(n);
    }

    void validate() {
        for (edge &e: edges) {
            if (e.flw < e.cap) {
                int x = e.src;
                int y = e.dst;
                assert (e.cost + phi[x] - phi[y] >= 0);
            }
        }
    }

    long cost = 0;

    void doubleFlow() {
        for (auto &e: edges) {
            e.cap *= 2;
            e.flw *= 2;
        }
        cost *= 2;
    }

    void incCapacity(int i) {
        auto &e = edges[i];
        auto &er = edges[i ^ 1];
        {
            if (e.cost + phi[e.src] - phi[e.dst] >= 0) {
                e.cap++;
                return;
            }
        }
        int n = graph.size();
        vector<long> dist(n);
        vector<int> prev(n);
        int s = e.dst;
        int t = e.src;
        dijkstra(s, dist, prev);
        long d2 = dist[t] - phi[s] + phi[t];
        if (d2 + e.cost < 0) {
            i = t;
            while (i != s) {
                edge &e = edges[prev[i]];
                edge &er = edges[prev[i] ^ 1];
                e.flw++;
                er.flw--;
                cost += (long) e.cost;
                i = e.src;
            }
            e.flw++;
            er.flw--;
        }
        e.cap++;
        for (int i = 0; i < n; i++) {
            if (dist[i] != INF) phi[i] += dist[i];
        }
        long dd = 0;
        for (auto &e: edges) {
            if (e.flw == e.cap) continue;
            long c = e.cost + phi[e.src] - phi[e.dst];
            dd = max(dd, -c);
        }
        for (int i = 0; i < n; i++) {
            if (dist[i] == INF) phi[i] += dd;
        }
        validate();
    }

    void minCostCirculation() {
        int n = graph.size();
        int m = edges.size() / 2;
        validate();
        for (int i = 30; i >= 0; i--) {
            doubleFlow();
            for (int j = 0; j < m; j++) {
                if (edges[2 * j].maxCap & (1 << i)) {
                    incCapacity(2 * j);
                }
            }
        }
    }

    void fordBellman() {
        int n = graph.size();
        for (int i = 0; i < n; i++) {
            phi[i] = INF;
        }
        bool ok = false;
        int c = 0;
        while (!ok) {
            c++;
            assert(c <= n);
            ok = true;
            for (edge &e: edges) {
                if (e.flw < e.cap) {
                    int x = e.src;
                    int y = e.dst;
                    if (phi[y] > phi[x] + e.cost) {
                        phi[y] = phi[x] + e.cost;
                        ok = false;
                    }
                }
            }
        }
    }

    int minCostFlow(int s, int t) {
        int n = graph.size();
        int m = edges.size();
        for (auto &e: edges) e.cap = e.maxCap;
        fordBellman();
        vector<long> dist(n);
        vector<int> prev(n);
        int fl = 0;
        while (true) {
            dijkstra(s, dist, prev);
            if (dist[t] == INF) break;
//            if (dist[t] - phi[s] + phi[t] >= 0) break;
            {
                int i = t;
                int delta = INT_MAX;
                while (i != s) {
                    edge &e = edges[prev[i]];
                    delta = std::min(delta, e.cap - e.flw);
                    i = e.src;
                }
                assert(delta >= 0);
                fl += delta;
                i = t;
                while (i != s) {
                    edge &e = edges[prev[i]];
                    edge &er = edges[prev[i] ^ 1];
                    e.flw += delta;
                    er.flw -= delta;
                    assert(e.flw <= e.cap);
                    cost += (long) e.cost * delta;
                    i = e.src;
                }
            }
            for (int i = 0; i < n; i++) {
                phi[i] += dist[i];
            }
        }
        return fl;
    }

    void addEdge(int u, int v, int cap, int cost) {
        edges.push_back({u, v, cap, cost, 0, 0});
        edges.push_back({v, u, 0, -cost, 0, 0});
        graph[u].push_back(edges.size() - 2);
        graph[v].push_back(edges.size() - 1);
    }
};


int main() {
    ios::sync_with_stdio(false);

    int n;
    cin >> n;
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        int x, y;
        cin >> x >> y;
        a[i] = x - y;
    }
    mincost mc;
    mc.init(n + 2);
    int s = n;
    int t = n + 1;
    for (int i = 0; i < n; i++) {
        if (a[i] < 0) {
            mc.addEdge(s, i, -a[i], 0);
        } else {
            mc.addEdge(i, t, a[i], 0);
        }
        if (i < n - 1) {
            mc.addEdge(i, i + 1, INT_MAX, 1);
            mc.addEdge(i + 1, i, INT_MAX, 1);
        }
    }
    mc.minCostFlow(s, t);
    cout << mc.cost << "\n";

    return 0;
}

컴파일 시 표준 에러 (stderr) 메시지

bulves.cpp: In member function 'void mincost::dijkstra(int, std::vector<long long int>&, std::vector<int>&)':
bulves.cpp:32:31: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   32 |             for (int j = 0; j < graph[v].size(); ++j) {
      |                             ~~^~~~~~~~~~~~~~~~~
bulves.cpp: In member function 'void mincost::minCostCirculation()':
bulves.cpp:116:13: warning: unused variable 'n' [-Wunused-variable]
  116 |         int n = graph.size();
      |             ^
bulves.cpp: In member function 'int mincost::minCostFlow(int, int)':
bulves.cpp:155:13: warning: unused variable 'm' [-Wunused-variable]
  155 |         int m = edges.size();
      |             ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...