Cod sursa(job #2960262)

Utilizator ctimburCristina T ctimbur Data 3 ianuarie 2023 21:55:07
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.19 kb
#include <climits>
#include <fstream>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

int n, m, source, dest, costMin;
vector<vector<int> > adjList, capac, cost_arc;
vector<int> cost_init, costuri, cost_actual;

bool Dijkstra() {
    int i, curr_node, curr_node_dist, j, new_node, new_cost, capMin = INT_MAX, newDest = dest, costActual = 0;
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq;
    vector<int> parinte;
    parinte.clear();
    parinte.resize(n + 1);

    for (i = 1; i <= n; i++)
        costuri[i] = INT_MAX;

    costuri[source] = 0;
    cost_actual[source] = 0;
    pq.push(make_pair(0, source));

    while(!pq.empty()) {
        curr_node = pq.top().second;
        curr_node_dist = pq.top().first;
        pq.pop();

        if(costuri[curr_node] == curr_node_dist)
            for(j = 0; j < adjList[curr_node].size(); j++) {
                new_node = adjList[curr_node][j];
                // Mai este capacitate de flux ramasa.
                if(capac[curr_node][new_node] > 0) {
                    new_cost = costuri[curr_node] + cost_arc[curr_node][new_node] + cost_init[curr_node] - cost_init[new_node];
                    if (new_cost < costuri[new_node]) {
                        costuri[new_node] = new_cost;
                        cost_actual[new_node] = cost_actual[curr_node] + cost_arc[curr_node][new_node];
                        parinte[new_node] = curr_node;
                        pq.push(make_pair(costuri[new_node], new_node));
                    }
                }
            }
    }

    for (i = 1; i <= n; i++)
        cost_init[i] = cost_actual[i];
    // Nu s-a ajuns la destinatie.
    if (costuri[dest] == INT_MAX)
        return false;

    while (newDest != source) {
        capMin = min(capMin, capac[parinte[newDest]][newDest]);
        costActual += cost_arc[parinte[newDest]][newDest];
        newDest = parinte[newDest];
    }

    costMin += capMin * cost_actual[dest];
    newDest = dest;

    // Parcurg din nou drumul de ameliorare.
    while(newDest != source) {
        // Scad capacitatea pentru drumurile parcurse.
        capac[parinte[newDest]][newDest] -= capMin;
        // Pentru muchia inversa, maresc capacitatea.
        capac[newDest][parinte[newDest]] += capMin;
        newDest = parinte[newDest];
    }

    return true;
}


void BellmanFord() {
    int i, curr_node, j, new_node;
    queue<int> q;
    vector<int> is_in_q(n + 1, 0);

    for(i = 1; i <= n; i++)
        cost_init[i] = INT_MAX;

    cost_init[source] = 0;
    q.push(source);
    is_in_q[source] = 1;

    while (!q.empty()) {
        curr_node = q.front();
        q.pop();
        // Nodul nu mai e in queue.
        is_in_q[curr_node] = 0;

        for(j = 0; j < adjList[curr_node].size(); j++) {
            new_node = adjList[curr_node][j];

            if(capac[curr_node][new_node])
                if(cost_init[curr_node] + cost_arc[curr_node][new_node] < cost_init[new_node]) {
                    cost_init[new_node] = cost_init[curr_node] + cost_arc[curr_node][new_node];
                    // Adaug in queue daca nu e.
                    if (is_in_q[new_node] == 0) {
                        is_in_q[new_node] = 1;
                        q.push(new_node);
                    }
                }
        }
    }
}

int main() {
    int i, nod1, nod2, cap, cost;

    fin >> n >> m >> source >> dest;
    
    adjList.resize(n + 1);
    capac.resize(n + 1);
    cost_arc.resize(n + 1);
    costuri.resize(n + 1, 0);
    cost_actual.resize(n + 1, 0);
    cost_init.resize(n + 1, 0);
    for(i = 0; i <= n; i++) {
        capac[i].resize(n + 1, 0);
        cost_arc[i].resize(n + 1, 0);
    }

    for (int i = 0; i < m; i++) {
        fin >> nod1 >> nod2 >> cap >> cost;
        adjList[nod1].push_back(nod2);
        adjList[nod2].push_back(nod1);
        capac[nod1][nod2] = cap;
        cost_arc[nod1][nod2] = cost;
        // Costul arcului invers este minusul costului arcului.
        cost_arc[nod2][nod1] = -cost;
    }

    BellmanFord();

    // Atata timp cat mai exista drumuri de ameliorare, inseamna ca mai putem adauga flux.
    while (Dijkstra());

    fout << costMin;

    return 0;
}