Cod sursa(job #2941033)

Utilizator MatteoalexandruMatteo Verzotti Matteoalexandru Data 17 noiembrie 2022 00:09:38
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.49 kb
#include <bits/stdc++.h>
#ifdef BLAT
    #include "debug/debug.hpp"
#else
    #define debug(x...)
#endif

using namespace std;

ifstream in ("fmcm.in");
ofstream out ("fmcm.out");

const int INF = 1e9;

class FlowGraph {
private:
    struct Edge {
        int from, to, cap, cost;
        int nxt;
    };

    int n;
    vector <int> graph, p, pi;
    vector <Edge> edges;

public:
    FlowGraph(int _n) : n(_n) {
        graph.resize(_n, -1);
    }

    void addEdge(int from, int to, int cap, int cost) {
        auto add = [&](int from, int to, int cap, int cost) {
            edges.push_back(Edge{from, to, cap, cost, graph[from]});
            graph[from] = edges.size() - 1;
        };
        add(from, to, cap, cost);
        add(to, from, 0, -cost);
    }

    void bellmanFord(int s) {
        vector <int> dist(n, INF);
        dist[s] = 0;
        p.assign(n, -1);

        vector <bool> inqueue(n, false);
        queue <int> q;
        q.push(s);

        while (!q.empty()) {
            int from = q.front();
            q.pop();
            inqueue[from] = false;

            for (int i = graph[from]; i != -1; i = edges[i].nxt) {
                Edge e = edges[i];
                if (e.cap && dist[e.to] > dist[e.from] + e.cost) {
                    dist[e.to] = dist[e.from] + e.cost;
                    p[e.to] = i;

                    if (!inqueue[e.to]) {
                        inqueue[e.to] = true;
                        q.push(e.to);
                    }

                }
            }
        }

        pi = dist;
    }

    bool dijkstra(int s, int t) {
        vector <int> dist(n, INF); dist[s] = 0;
        p.assign(n, -1);

        priority_queue <pair <int, int>> pq;
        pq.push(make_pair(0, s));

        while (!pq.empty()) {
            auto [d, from] = pq.top(); pq.pop();
            if (d != -dist[from]) continue;

            for (int i = graph[from]; i != -1; i = edges[i].nxt) {
                Edge e = edges[i];
                if (e.cap && dist[e.to] > dist[e.from] + pi[e.from] - pi[e.to] + e.cost) {
                    dist[e.to] = dist[e.from] + pi[e.from] - pi[e.to] + e.cost;
                    p[e.to] = i;
                    
                    pq.push(make_pair(-dist[e.to], e.to));
                }
            }
        }
        for (int i = 0; i < n; i++)
            pi[i] = min(pi[i] + dist[i], INF);
        return p[t] != -1;
    }

    pair <int, int> minCostMaxFlow(int s, int t) {
        int maxFlow = 0;
        int minCost = 0;

        bellmanFord(s);

        while (dijkstra(s, t)) {
            int flow = INF;
            for (int edge = p[t]; edge != -1; edge = p[edges[edge].from])
                flow = min(flow, edges[edge].cap);

            // debug(flow);
            for (int edge = p[t]; edge != -1; edge = p[edges[edge].from]) {
                edges[edge].cap -= flow;
                edges[edge ^ 1].cap += flow;
                minCost += edges[edge].cost * flow;
            }

            maxFlow += flow;
        }

        return make_pair(minCost, maxFlow);
    }
};

int main() {
    int n, m, s, d;
    in >> n >> m >> s >> d;
    s--; d--;
    
    FlowGraph graph(n);
    for (int i = 0; i < m; i++) {
        int from, to, cap, cost;
        in >> from >> to >> cap >> cost;
        from--; to--;
        graph.addEdge(from, to, cap, cost);
    }

    out << graph.minCostMaxFlow(s, d).first << '\n';
    return 0;
}