Cod sursa(job #2940635)

Utilizator MatteoalexandruMatteo Verzotti Matteoalexandru Data 15 noiembrie 2022 23:34:32
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.6 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> rem, graph, p;
    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);
    }

    bool bellmanFord(int s, int t) {
        vector <int> d(n, INF);
        d[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 && d[e.to] > d[e.from] + e.cost) {
                    d[e.to] = d[e.from] + e.cost;
                    p[e.to] = i;

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

                }
            }
        }

        return (d[t] != INF);
    }

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

        while (bellmanFord(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;
}