Cod sursa(job #3125947)

Utilizator ptudortudor P ptudor Data 4 mai 2023 20:32:29
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.67 kb
#include <bits/stdc++.h>
#define int long long
using namespace std;

#ifdef LOCAL
ifstream in("in.in");
ofstream out("out.out");
#else
ifstream in("fmcm.in");
ofstream out("fmcm.out");
#endif

namespace MaxFlow {
    struct Edge {
        int to,rev,cap,cost,flow = 0;
    };

    const int inf = 1000000005;
    int n,s,t;
    vector<vector<Edge>> g;
    void init(int N) {
        n = N;
        g.resize(n + 1);
    }
    void add_edge(int u, int v, int flow, int cost) {
        g[u].push_back(Edge{v, (int)g[v].size(), flow, cost});
        g[v].push_back(Edge{u, (int)g[u].size() - 1, 0, -cost});
    }

    void set_sink(int S, int T) {
        s = S;
        t = T;
    }


    int get_free(Edge x) {
        return x.cap - x.flow;
    }

    vector<int> real_dis;
    
    void bellman() {
        real_dis = vector<int>(n + 1, inf);

        priority_queue<pair<int,int>> q;
        real_dis[s] = 0;
        q.push({0,s});
        while(!q.empty()) {
            int node = q.top().second;
            int cost = -q.top().first;
            q.pop();
            if (cost > real_dis[node]) {
                continue;
            }

            for (auto k : g[node]) {
                if (k.cap - k.flow > 0 && real_dis[node] + k.cost < real_dis[k.to]) {
                    real_dis[k.to] = real_dis[node] + k.cost;
                    q.push({-real_dis[k.to] , k.to});
                }
            }
        }
    }
    
    pair<int,int> add_flow() {
        vector<int> dis(n + 1, inf),from_edge(n + 1),from_node(n + 1);
        priority_queue<pair<int,int>> q;
        dis[s] = 0;
        q.push({0,s});
        while(!q.empty()) {
            int node = q.top().second;
            int cost = -q.top().first;
            q.pop();
            if (cost > dis[node]) {
                continue;
            }

            for (auto k : g[node]) {
                if (k.cap - k.flow > 0 && dis[node] + k.cost < dis[k.to]) {
                    dis[k.to] = dis[node] + k.cost;
                    from_edge[k.to] = k.rev;
                    q.push({-dis[k.to] , k.to});
                }
            }
        }

        if (dis[t] == inf) {
            return {0,0};
        }

        int node = t,bottle_neck = inf;
        while(node != s) {
            int from = g[node][from_edge[node]].to;
            int edge = g[node][from_edge[node]].rev;

            bottle_neck = min(bottle_neck,get_free(g[from][edge]));
            node = from;
        }

        int cost = 0;
        node = t;
        while(node != s) {
            int from = g[node][from_edge[node]].to;
            int edge = g[node][from_edge[node]].rev;
        
            cost += (g[from][edge].cost - real_dis[from] + real_dis[node]) * bottle_neck;
            g[from][edge].flow += bottle_neck;
            g[node][from_edge[node]].flow -= bottle_neck;
            node = from;
        }

        return {bottle_neck, cost};
    }

    pair<int,int> compute() {
        int flow = 0, cost = 0;

        bellman();
        for (int i = 1; i <= n; i++) {
            for (auto &k : g[i]) {
                k.cost += real_dis[i] - real_dis[k.to];
            }
        }

        while(true) {
            auto added_flow = add_flow();
            if (added_flow.first == 0) {
                break;
            }

            flow += added_flow.first;
            cost += added_flow.second;
        }        
        return {flow , cost};
    }
}
int32_t main() {
    int n,m,s,d;
    in >> n >> m >> s >> d;
    MaxFlow :: init(n);
    MaxFlow :: set_sink(s,d);

    for (int i = 1; i <= m; i++) {
        int u,v,cap,cost;
        in >> u >> v >> cap >> cost;
        MaxFlow :: add_edge(u,v,cap,cost);
    }

    out << MaxFlow :: compute().second << "\n";    
}