Cod sursa(job #1670807)

Utilizator RazvanR104Razvan-Andrei Ciocoiu RazvanR104 Data 1 aprilie 2016 01:01:37
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.23 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 400, inf = 0x3f3f3f3f;

struct Edge {
    int from, to, cap, cost, flow;
    Edge *rev;

    Edge(int from, int to, int cap, int cost) :
        from(from),
        to(to),
        cap(cap),
        cost(cost),
        flow(0),
        rev(0) {
    }
};

int N, M, S, D;
vector<Edge *> G[NMAX];

void AddEdge(int from, int to, int cap, int cost) {
    Edge *dir = new Edge(from, to, cap, cost);
    Edge *rev = new Edge(to, from, 0, -cost);

    dir->rev = rev;
    rev->rev = dir;

    G[from].push_back(dir);
    G[to].push_back(rev);
}

int dist[NMAX];
bool inq[NMAX];
Edge *father[NMAX];
bool BellmanFord(int S, int D) {
    memset(dist, inf, sizeof dist);
    dist[S] = 0;

    queue<int> Q;
    Q.push(S);
    inq[S] = 1;

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

        for (const auto &it: G[now]) {
            if (it->cap - it->flow == 0)
                continue;
            if (dist[it->to] > dist[it->from] + it->cost) {
                dist[it->to] = dist[it->from] + it->cost;
                father[it->to] = it;

                if (inq[it->to] == 0) {
                    Q.push(it->to);
                    inq[it->to] = 1;
                }
            }
        }
    }

    return dist[D] != inf;
}

int MaxFlowMinCost(int S, int D) {
    int answer = 0;
    while (BellmanFord(S, D)) {
        int add = inf;

        Edge *curr = father[D];
        while (curr != 0) {
            add = min(add, curr->cap - curr->flow);
            curr = father[curr->from];
        }

        curr = father[D];
        while (curr != 0) {
            curr->flow += add;
            curr->rev->flow -= add;
            curr = father[curr->from];
        }

        answer += dist[D] * add;
    }

    return answer;
}

int main() {
    assert(freopen("fmcm.in", "r", stdin));
    assert(freopen("fmcm.out", "w", stdout));

    int i;
    int x, y, c, z;

    cin >> N >> M >> S >> D;
    for (i = 1; i <= M; ++i) {
        cin >> x >> y >> c >> z;
        AddEdge(x, y, c, z);
    }

    cout << MaxFlowMinCost(S, D) << '\n';

    return 0;
}