Cod sursa(job #1670820)

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

#define x first
#define y second

using namespace std;

const int NMAX = 400, inf = 0x3f3f3f3f;

int N, M, S, D;
int F[NMAX][NMAX], C[NMAX][NMAX];
vector<pair<int, int>> G[NMAX];

void AddEdge(int from, int to, int cap, int cost) {
    C[from][to] = cap;
    C[to][from] = 0;

    G[from].push_back({to, cost});
    G[to].push_back({from, -cost});
}

int dist[NMAX];
bool inq[NMAX];
void BellmanFord(int S) {
    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 (C[now][it.x] == 0)
                continue;

            if (dist[it.x] > dist[now] + it.y) {
                dist[it.x] = dist[now] + it.y;

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

int dist2[NMAX], rdist[NMAX];
int father[NMAX];
bool Dijkstra(int S, int D) {
    memset(dist2, inf, sizeof dist2);
    memset(rdist, 0, sizeof rdist);
    dist2[S] = 0;

    priority_queue<pair<int, int>> PQ;
    PQ.push({0, S});

    while (!PQ.empty()) {
        int cost, node;
        tie(cost, node) = PQ.top();
        PQ.pop();

        if (node == D)
            return 1;

        if (dist2[node] != -cost)
            continue;

        for (const auto &it: G[node]) {
            if (C[node][it.x] - F[node][it.x] == 0)
                continue;

            if (dist2[it.x] > dist2[node] + it.y + dist[node] - dist[it.x]) {
                dist2[it.x] = dist2[node] + it.y + dist[node] - dist[it.x];
                rdist[it.x] = rdist[node] + it.y;

                father[it.x] = node;

                PQ.push({-dist2[it.x], it.x});
            }
        }
    }

    return 0;
}

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

        int curr = D;
        while (father[curr] != 0) {
            add = min(add, C[father[curr]][curr] - F[father[curr]][curr]);
            curr = father[curr];
        }

        curr = D;
        while (father[curr] != 0) {
            F[father[curr]][curr] += add;
            F[curr][father[curr]] -= add;
            curr = father[curr];
        }

        answer += rdist[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;

    scanf("%d %d %d %d", &N, &M, &S, &D);
    for (i = 1; i <= M; ++i) {
        scanf("%d %d %d %d", &x, &y, &c, &z);
        AddEdge(x, y, c, z);
    }

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

    return 0;
}