Cod sursa(job #2254007)

Utilizator UncleGrandpa925Hoang Long Vuong UncleGrandpa925 Data 4 octombrie 2018 18:13:25
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.61 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 355
#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;
}

class MinCostMaxFlow {
    vector<int> a[N];
    int cap[N][N], cost[N][N];
    int pre[N], dis[N];
    int h[N], hsize, newd[N], idx[N], aux[N];
    int q[130000], vis[N];
    int n;
    const int INF = 1e9 + 7;
    int cmin = INF;

    bool bfs(int s, int d) {
        memset(vis, 0, sizeof(vis));
        vis[s] = 1;
        int st = 1, en = 1;
        for (int i = 1; i <= n; i++)
            dis[i] = INF;
        dis[s] = 0; q[st] = s; pre[s] = -1;
        while (st <= en) {
            int u = q[st];
            ++st;
            vis[u] = 0;
            for (auto it : a[u]) {
                if (!(cap[u][it] > 0 && dis[u] + cost[u][it] < dis[it])) continue;
                dis[it] = dis[u] + cost[u][it];
                if (!vis[it]) {
                    ++en;
                    q[en] = it;
                    vis[it] = true;
                }
                pre[it] = u;
            }
        }
        if (dis[d] != INF) return true;
        return 0;
    }

    void downh() {
        int aux = 1;
        while (aux * 2 <= hsize) {
            int index = aux;
            if (newd[h[2 * aux]] < newd[h[aux]]) index = 2 * aux;
            if (2 * aux + 1 <= hsize && newd[h[2 * aux + 1]] < newd[h[index]])
                index = 2 * aux + 1;
            if (index == aux) break;
            swap(idx[h[aux]], idx[h[index]]);
            swap(h[aux], h[index]);
            aux = index;
        }

    }
    void uph(int x) {
        while (x > 1 && newd[h[x / 2]] > newd[h[x]]) {
            swap(idx[h[x]], idx[h[x / 2]]);
            swap(h[x / 2], h[x]);
            x /= 2;
        }
    }

    bool existFlow(int s, int d) {
        memset(pre, 0, sizeof(pre));
        aux[s] = 0;
        pre[s] = -1;
        for (int i = 1; i <= n; ++i) {
            h[i] = idx[i] = i;
            newd[i] = INF;
        }
        newd[s] = 0;
        h[1] = idx[1] = s;
        h[s] = idx[s] = 1;
        hsize = n;
        while (hsize > 0) {
            int nodc = h[1];
            idx[h[hsize]] = 1;
            h[1] = h[hsize];
            --hsize;
            downh();
            int costm = 0;
            for (auto it : a[nodc]) {
                if (cap[nodc][it] <= 0) continue;
                costm = dis[nodc] + cost[nodc][it] - dis[it] ;
                if (newd [it] > newd[nodc] + costm) {
                    newd[it] = newd[nodc] + costm;
                    pre[it] = nodc;
                    uph(idx[it]);
                    aux[it] = aux[nodc] + cost[nodc][it];
                }
            }
        }
        return pre[d] != 0;
    }
public:
    void init(int _n) {
        n = _n;
        for (int i = 1; i <= n; i++)a[i].clear();
    }
    void addEdge(int u, int v, int Cap, int Cost) {
        a[u].push_back(v);
        cap[u][v] = Cap;
        cost[u][v] = Cost;
        a[v].push_back(u);
        cap[v][u] = 0;
        cost[v][u] = -Cost;
    }
    pair<int, int> solve(int S, int T) {
        int flux = 0, costf = 0;
        bfs(S, T);
        for (int i = 1; i <= n; ++i)
            aux[i] = dis[i];
        int nod = T;
        while (existFlow(S, T)) {
            for (int i = 1; i <= n; i++)
                dis[i] = aux[i];
            nod = T;
            cmin = INF;
            while (nod != S) {
                cmin = min(cmin, cap[pre[nod]][nod]);
                nod = pre[nod];
            }
            flux += cmin;
            costf += dis[T] * cmin;
            nod = T;
            while (nod != S) {
                cap[nod][pre[nod]] += cmin; cap[pre[nod]][nod] -= cmin;
                nod = pre[nod];
            }
        }
        return mp(costf, flux);
    }
} MF;

int n, m, S, T;
int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);
    cin >> n >> m >> S >> T;
    MF.init(n);
    for (int i = 1; i <= m; ++i) {
        int u, v, x, y;
        cin >> u >> v >> x >> y;
        MF.addEdge(u, v, x, y);
    }
    auto rec = MF.solve(S, T);
    cout << rec.fi << endl;
}