Cod sursa(job #1579136)

Utilizator retrogradLucian Bicsi retrograd Data 24 ianuarie 2016 14:25:18
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.03 kb
#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>

using namespace std;

struct Flow {
    const static int MAX_EDGES = 25005;
    const static int MAX_NODES = 360;
    const int INF = 1e9 + 50;

    int S = MAX_NODES - 2, D = MAX_NODES - 1;

    int G[MAX_NODES];
    struct Edge {
        int vec, flow, cap, cost, rev, nxt;
    };
    Edge E[MAX_EDGES];
    int edges = 0;

    int ParentNode[MAX_NODES], ParentEdge[MAX_NODES], Dist[MAX_NODES], DistOld[MAX_NODES], DistReal[MAX_NODES];
    bool InQ[MAX_NODES];
    queue<int> Q;
    priority_queue<pair<int, int>> PQ;

    Flow() {
        Reset();
    }

    void setSource(int s) {
        S = s;
    }
    void setSink(int d) {
        D = d;
    }

    void _addEdge(int a, int b, int cap, int cost, int rev) {
        ++edges;
        E[edges] = (Edge) {b, 0, cap, cost, rev, G[a]};
        G[a] = edges;
    }
    void AddEdge(int a, int b, int cap, int cost) {
        _addEdge(a, b, cap, cost, edges + 2);
        _addEdge(b, a, 0, -cost, edges);
    }

    bool Bellman() {
        memset(ParentNode, 0, sizeof(ParentNode));

        DistOld[S] = 0;
        Q.push(S);


        while(!Q.empty()) {
            int top = Q.front();
            InQ[top] = 0;
            Q.pop();

            for(int i=G[top]; i; i=E[i].nxt) {
                int vec = E[i].vec;
                if(E[i].flow < E[i].cap && (ParentNode[vec] == 0 || DistOld[vec] > DistOld[top] + E[i].cost)) {
                    DistOld[vec] = DistOld[top] + E[i].cost;
                    ParentNode[vec] = top;
                    ParentEdge[vec] = i;

                    if(!InQ[vec]) {
                        Q.push(vec);
                        InQ[vec] = 1;
                    }
                }
            }
        }

        return ParentNode[D] != 0;
    }

    bool Dijkstra() {
        memset(ParentNode, 0, sizeof(ParentNode));

        Dist[S] = DistReal[S] = 0;
        PQ.push({0, S});

        while(!PQ.empty()) {
            auto top = PQ.top();
            PQ.pop();
            int node = top.second;

            if(-top.first > Dist[node])
                continue;

            for(int i = G[node]; i; i = E[i].nxt) {
                int vec = E[i].vec;

                if(E[i].flow < E[i].cap && (ParentNode[vec] == 0 || Dist[vec] > Dist[node] + DistOld[node] - DistOld[vec] + E[i].cost)) {
                    Dist[vec] = Dist[node] + DistOld[node] - DistOld[vec] + E[i].cost;
                    ParentNode[vec] = node;
                    ParentEdge[vec] = i;
                    DistReal[vec] = DistReal[node] + E[i].cost;
                    PQ.push({-Dist[vec], vec});
                }
            }
        }

        return ParentNode[D] != 0;

    }

    void Reset() {
        edges = 0;
        memset(G, 0, sizeof(G));
        while(!Q.empty()) Q.pop();
        while(!PQ.empty()) PQ.pop();
    }

    int MFMC() {
        int cost = 0, flow = 0;

        Bellman();

        while(Dijkstra()) {
            int M = INF;

            for(int node = D; node != S; node = ParentNode[node]) {
                int ei = ParentEdge[node];
                M = min(M, E[ei].cap - E[ei].flow);
            }

            for(int node = D; node != S; node = ParentNode[node]) {
                int ei = ParentEdge[node],
                    ri = E[ei].rev;

                E[ei].flow += M;
                E[ri].flow -= M;

                cost += E[ei].cost * M;
            }

            flow += M;
            memcpy(DistOld, DistReal, sizeof(DistReal));
        }

        return cost;
    }

};
Flow F;

int main() {
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);
    ios_base::sync_with_stdio(false);

    int n, m, s, d, a, b, c;
    cin >> n >> m >> s >> d;

    F.setSource(s);
    F.setSink(d);

    while(m--) {
        cin >> a >> b >> c >> d;
        F.AddEdge(a, b, c, d);
    }

    cout << F.MFMC() << '\n';

    return 0;
}