Cod sursa(job #2252912)

Utilizator UncleGrandpa925Hoang Long Vuong UncleGrandpa925 Data 3 octombrie 2018 11:52:56
Problema Flux maxim de cost minim Scor 60
Compilator cpp Status done
Runda Arhiva educationala Marime 4.44 kb
/*input
5 7 2 5
3 1 7 -1
1 4 3 0
3 4 3 -4
1 5 7 0
4 5 1 1
2 5 8 -3
2 3 4 -3
*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define N
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)(l); i<=(int)(r); i++)

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}

// Source: rng_58: http://codeforces.com/contest/277/submission/3212642
// Fast min cost max flow (Dijkstra)
// Index from 0
// NOTE!!!!!! Flow through both direction can be < 0
// --> need to be careful when trace
// Does not work when cost < 0

#define F_INF 1000000000
#define C_INF 1000000000

template<class Flow = int, class Cost = int>
struct MinCostFlow {
    int V, E;
    vector<Flow> cap;
    vector<Cost> cost;
    vector<int> to, prev;

    vector<Cost> dist, pot;
    vector<int> last, path, used;
    priority_queue< pair<Cost, int> > q;

    MinCostFlow(int V, int E) : V(V), E(0), cap(E * 2, 0), cost(E * 2, 0), to(E * 2, 0), prev(E * 2, 0),
        dist(V, 0), pot(V, 0), last(V, -1), path(V, 0), used(V, 0) {}

    int addEdge(int x, int y, Flow f, Cost c) {
        cap[E] = f; cost[E] = c; to[E] = y; prev[E] = last[x]; last[x] = E; E++;
        cap[E] = 0; cost[E] = -c; to[E] = x; prev[E] = last[y]; last[y] = E; E++;
        return E - 2;
    }

    pair<Flow, Cost> search(int s, int t) {
        Flow ansf = 0; Cost ansc = 0;
        for (int i = 0; i < V; i++) used[i] = false;
        for (int i = 0; i < V; i++) dist[i] = C_INF;

        dist[s] = 0; path[s] = -1; q.push(make_pair(0, s));
        while (!q.empty()) {
            int x = q.top().second; q.pop();
            if (used[x]) continue; used[x] = true;
            for (int e = last[x]; e >= 0; e = prev[e]) if (cap[e] > 0) {
                    Cost tmp = dist[x] + cost[e] + pot[x] - pot[to[e]];
                    if (tmp < dist[to[e]] && !used[to[e]]) {
                        dist[to[e]] = tmp;
                        path[to[e]] = e;
                        q.push(make_pair(-dist[to[e]], to[e]));
                    }
                }
        }
        for (int i = 0; i < V; i++) pot[i] += dist[i];
        if (used[t]) {
            ansf = F_INF;
            for (int e = path[t]; e >= 0; e = path[to[e ^ 1]]) ansf = min(ansf, cap[e]);
            for (int e = path[t]; e >= 0; e = path[to[e ^ 1]]) { ansc += cost[e] * ansf; cap[e] -= ansf; cap[e ^ 1] += ansf; }
        }
        return make_pair(ansf, ansc);
    }
    pair<Flow, Cost> minCostFlow(int s, int t) {
        Flow ansf = 0; Cost ansc = 0;
        while (1) {
            pair<Flow, Cost> p = search(s, t);
            if (!used[t]) break;
            ansf += p.first; ansc += p.second;
        }
        return make_pair(ansf, ansc);
    }
};

int n, m, S, T;
signed main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);
    read(n); read(m); read(S); read(T);
    MinCostFlow<> MCMF(n + 5, m + 5);
    loop(i, 1, m) {
        int u, v, cap, cost;
        read(u); read(v); read(cap); read(cost);
        MCMF.addEdge(u, v, cap, cost);
    }
    cout << MCMF.minCostFlow(S, T).se << endl;
}