Cod sursa(job #2945095)

Utilizator Cosmin2004_InfoMoldoveanu Cosmin Cosmin2004_Info Data 23 noiembrie 2022 14:23:41
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.13 kb
#include <bits/stdc++.h>

using namespace std;
class MinCostMaxFlow {
    const int inf = 1e9;
    struct edge {
        int from, to, cap, cost;
    };
    struct heapnode { int cost, node; friend bool operator <(const heapnode& a, const heapnode& b) { return a.cost > b.cost; } };;
    int n;
    vector <edge> edges;
    vector <vector <int>> g;
    vector <int> d, dist, from;
    int s, t;
public:
    MinCostMaxFlow(int n) : n(n), g(n + 1), d(n + 1, 0), dist(n + 1, 0), from(n + 1, -1), s(1), t(n) {}
    void add_edge(int u, int v, int w, int c) {
        g[u].push_back(edges.size());
        edges.push_back({u, v, w, c});
        g[v].push_back(edges.size());
        edges.push_back({v, u, 0, -c});
    }
    void bellman() {
        vector <bool> inq(n + 1, false);
        queue <int> q; fill(d.begin(), d.end(), inf); d[s] = 0;
        for(q.push(s); !q.empty(); q.pop()) {
            int u = q.front();
            inq[u] = false;
            for(int id : g[u]) {
                auto [uu, v, cap, cost] = edges[id];
                if(cap && d[v] > d[u] + cost) {
                    d[v] = d[u] + cost;
                    if(!inq[v]) {
                        inq[v] = true;
                        q.push(v);
                    }
                }
            }
        }
    }
    bool dijkstra() {
        fill(dist.begin(), dist.end(), inf);
        fill(from.begin(), from.end(), -1);
        dist[s] = 0;
        priority_queue <heapnode> pq;
        vector <bool> vis(n + 1, false);
        pq.push({0, s});
        while(!pq.empty()) {
            auto [dd, u] = pq.top();
            pq.pop();
            if(vis[u]) continue;
            vis[u] = true;
            for(int id : g[u]) {
                auto [uu, v, cap, cost] = edges[id];
                if(cap && dist[u] + cost + d[u] - d[v] < dist[v]) {
                    dist[v] = dist[u] + cost + d[u] - d[v];
                    pq.push({dist[v], v});
                    from[v] = id;
                }
            }
        }
        from[s] = -1;
        for(int i = 0; i <= n; i++)
            d[i] = min(inf, d[i] + dist[i]);
        return (dist[t] != inf);
    }
    pair <int, int> flow(int s, int t) {
        this->s = s; this->t = t;
        bellman();
        long long max_flow = 0, min_cost = 0;
        while(dijkstra()) {
            int min_flow = inf;
            for(int i = from[t]; i != -1; i = from[edges[i].from])
                min_flow = min(min_flow, edges[i].cap);
            for(int i = from[t]; i != -1; i = from[edges[i].from]) {
                edges[i].cap -= min_flow;
                edges[i ^ 1].cap += min_flow;
                min_cost += 1ll * edges[i].cost * min_flow;
            }
            max_flow += min_flow;
        }
        return {max_flow, min_cost};
    }
};

int main()
{
    ifstream cin("fmcm.in");
    ofstream cout("fmcm.out");
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    MinCostMaxFlow F(n);
    for(int i = 0, u, v, w, c; i < m; i++)
        cin >> u >> v >> w >> c,
        F.add_edge(u, v, w, c);
    cout << F.flow(s, t).second;
    return 0;
}