Cod sursa(job #2899995)

Utilizator AlexandruabcdeDobleaga Alexandru Alexandruabcde Data 9 mai 2022 20:43:13
Problema Flux maxim de cost minim Scor 30
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.8 kb
#include <bits/stdc++.h>

using namespace std;

ifstream f ("fmcm.in");
ofstream g ("fmcm.out");

constexpr int NMAX = 355;
constexpr int INF = 1e9;

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

int cost[NMAX][NMAX];
int cap[NMAX][NMAX];
int flow[NMAX][NMAX];

void Add_Edge (int x, int y, int weight, int c) {
    G[x].push_back(y);
    G[y].push_back(x);

    cap[x][y] = weight;
    cost[x][y] = c;
    cost[y][x] = -c;
}

void Read () {
    f >> N >> M >> S >> D;

    for (int i = 1; i <= M; ++ i ) {
        int x, y, w, c;
        f >> x >> y >> w >> c;

        Add_Edge(x, y, w, c);
    }
}

bool viz[NMAX];
int PI[NMAX];
void Precompute () {
    for (int i = 1; i <= N; ++ i ) {
        viz[i] = false;
        PI[i] = INF;
    }
    PI[S] = 0;
    viz[S] = true;
    queue <int> Q;
    Q.push(S);

    while (!Q.empty()) {
        int nod = Q.front();
        Q.pop();
        viz[nod] = false;

        for (auto it : G[nod]) {
            if (cap[nod][it] > 0 && PI[it] > PI[nod] + cost[nod][it]) {
                PI[it] = PI[nod] + cost[nod][it];

                if (!viz[it]) {
                    viz[it] = true;
                    Q.push(it);
                }
            }
        }
    }
}

int New_Weight (int x, int y) {
    return cost[x][y] + PI[x] - PI[y];
}

int dist[NMAX];
int Dad[NMAX];

bool Path (int Start, int Finish) {
    for (int i = 1; i <= N; ++ i ) {
        dist[i] = INF;
        Dad[i] = -1;
        viz[i] = false;
    }

    priority_queue <pair <int, int>, vector <pair <int, int> >, greater <pair <int, int> > > Q;
    dist[Start] = 0;
    Q.push({0, Start});

    while (!Q.empty()) {
        while (!Q.empty() && viz[Q.top().second]) Q.pop();

        if (Q.empty()) break;
        int nod = Q.top().second;
        viz[nod] = true;
        Q.pop();

        for (auto it : G[nod]) {
            if (cap[nod][it] != flow[nod][it] && dist[nod] + New_Weight(nod, it) < dist[it]) {
                dist[it] = dist[nod] + New_Weight(nod, it);
                Dad[it] = nod;
                Q.push({dist[it], it});
            }
        }
    }

    return viz[Finish];
}

int CostMinim (int Start, int Finish) {
    int ans = 0;

    while (Path(Start, Finish)) {
        int F = INF;
        int modifier = 0;
        for (int nod = Finish; nod != Start; nod = Dad[nod]) {
            modifier += cost[Dad[nod]][nod];
            F = min(F, cap[Dad[nod]][nod] - flow[Dad[nod]][nod]);
        }

        ans += F * modifier;

        for (int nod = Finish; nod != Start; nod = Dad[nod]) {
            flow[Dad[nod]][nod] += F;
            flow[nod][Dad[nod]] -= F;
        }
    }

    return ans;
}

int main () {
    Read();
    Precompute();

    g << CostMinim(S, D) << '\n';
    return 0;
}